avatarAnupam Chugh

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

2996

Abstract

f">Enough talk. Let’s build our iOS application using PencilKit now.</p><h1 id="0d46">Implementation</h1><p id="74dd">We’ll be implementing the following things in our iOS application.</p><ul><li>Adding undo/redo draw actions for iOS devices</li><li>Saving drawing sketches to the photos library</li></ul><p id="f044">Set Privacy — Photo Library Additions Usage Description to <code>Allowed</code> in <code>Info.plist</code> in order to save images.</p><h1 id="68ca">Our Storyboard</h1><figure id="7a2f"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*MUMJfCnMAeHbKr8A.png"><figcaption>Built-in selectors are set on the undo and redo buttons</figcaption></figure><p id="a62d">For the undo and redo actions, we’ve used the built-in selectors.</p><h2 id="7887">Setting the Canvas View</h2><p id="682f">The following code sets the Canvas View for you:</p><div id="722a"><pre><span class="hljs-keyword">let</span> <span class="hljs-attr">canvasView</span> = PKCanvasView(frame: .zero) canvasView.<span class="hljs-attr">translatesAutoresizingMaskIntoConstraints</span> = <span class="hljs-literal">false</span></pre></div><div id="c70e"><pre><span class="hljs-keyword">view</span>.addSubview(canvasView)</pre></div><div id="46ad"><pre><span class="hljs-selector-tag">NSLayoutConstraint</span><span class="hljs-selector-class">.activate</span>([ canvasView.topAnchor.<span class="hljs-built_in">constraint</span>(<span class="hljs-attribute">equalTo</span>: navigationBar.bottomAnchor), canvasView.bottomAnchor.<span class="hljs-built_in">constraint</span>(<span class="hljs-attribute">equalTo</span>: view.bottomAnchor), canvasView.leadingAnchor.<span class="hljs-built_in">constraint</span>(<span class="hljs-attribute">equalTo</span>: view.leadingAnchor), canvasView.trailingAnchor.<span class="hljs-built_in">constraint</span>(<span class="hljs-attribute">equalTo</span>: view.trailingAnchor), ])</pre></div><h2 id="7372">Setting the ToolPicker</h2><ul><li>The initialization is done by asking for the shared ToolPicker for the window</li><li>Canvas View needs to be added as an observer to the ToolPicker</li><li><code>setVisible</code> true indicates that whenever the Canvas View becomes the first responder, the palette will show up</li></ul><div id="bf09"><pre>guard <span class="hljs-keyword">let</span> <span class="hljs-keyword">window</span> = view.<span class="hljs-keyword">window</span>, <span class="hljs-keyword">let</span> toolPicker = PKToolPicker.shared(for: <span class="hljs-keyword">window</span>) <span class="hljs-keyword">else</span> { <span class="hljs-keyword">return</span> }</pre></div><div id="fef8"><pre>toolPicker<span class="hljs-selector-class">.setVisible</span>(true, forFirstResponder: canvasView) toolPicker<span class="hljs-selector-class">.addObserver</span>(canvasView) canvasView<span class="hljs-selector-class">.becomeFirstResponder</span>()</pre></div><h2 id="a09c">Clear the Canvas View</h2><p id="398f">In order to clear the <code>PK

Options

CanvasView</code>, just reinitialize the <code>PKDrawing</code> instance.</p><div id="1c18"><pre><span class="hljs-attr">canvasView.drawing</span> = PKDrawing()</pre></div><h2 id="d8ce">Saving drawing to UIImage</h2><p id="6804"><code>func image(from rect: CGRect, scale: CGFloat)</code> is invoked on the PKDrawing instance.</p><p id="a502">It returns a <code>UIImage</code> of the portion of the drawing, we want to capture. The scale is typically set to 1.0. Set higher values for a more detailed image (useful for retina display).</p><div id="6d35"><pre><span class="hljs-built_in">let</span> <span class="hljs-built_in">image</span> = canvasView.drawing.<span class="hljs-built_in">image</span>(from: canvasView.drawing.bounds, <span class="hljs-built_in">scale</span>: <span class="hljs-number">1.0</span>)</pre></div><div id="8e5c"><pre><span class="hljs-built_in">UIImageWriteToSavedPhotosAlbum</span>(image, <span class="hljs-keyword">self</span>, <span class="hljs-literal">nil</span>, <span class="hljs-literal">nil</span>)</pre></div><p id="152e">Here’s the full source code of our PencilKit iOS 13 application:</p> <figure id="5fd5"> <div> <div>

            <iframe class="gist-iframe" src="/gist/anupamchugh/259f83f8922bc42ac553128395b9733a.js" allowfullscreen="" frameborder="0" height="undefined" width="undefined">
          </div>
        </div>
    </figure></iframe></div></div></figure><p id="a252">Here’s an output of the PencilKit application in action on an iPhone device:</p><figure id="5207"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*Ld4JMXpZzwVfVCRH.gif"><figcaption>Screengrab from my iPhone</figcaption></figure><h1 id="7127">Conclusion</h1><p id="ad6a">That sums up this introductory article on PencilKit in iOS 13. Now go draw and doodle with it.</p><p id="2f64">You can download the full source code from <a href="https://github.com/anupamchugh/iowncode/tree/master/iOSPencilKit">our Github repository</a>.</p><h1 id="3885">Next Part</h1><p id="e842">Yes, we have a sequel! We’ll be implementing Core ML alongside PencilKit by using the famous MNIST model in the <a href="https://readmedium.com/pencilkit-meets-core-ml-aefe3cde6a96">next part</a>.</p><p id="7ba9">If you’ve come this far and liked this article, here’s another one you may like:</p><div id="9264" class="link-block">
      <a href="https://readmedium.com/ios-13-checklist-for-developers-ef47e413aad2">
        <div>
          <div>
            <h2>iOS 13 Checklist For Developers</h2>
            <div><h3>A checklist to refer to when shipping your next app for iOS 13</h3></div>
            <div><p>medium.com</p></div>
          </div>
          <div>
            <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*fTWtsRRWS9LTUXAADNUtQg.jpeg)"></div>
          </div>
        </div>
      </a>
    </div></article></body>

An Introduction to PencilKit in iOS

Draw, undo, redo, and save in iOS 13

A result you can achieve at the end of this article.

WWDC 2019 introduced another interesting framework, PencilKit. It’s now available on iOS 13.

PencilKit allows developers to easily integrate the drawing canvas view and toolkit in their applications.

The goal of this article is to walk you through the PencilKit architecture and its implementation with a simple iOS application.

Note: PencilKit requires Xcode 11 and iOS 13.

PencilKit: Inside the Wood

  • PKCanvasView is the region inside where the drawing is possible. The user can draw all their art and doodles here. PKCanvasView allows panning and zooming since it's essentially a part of the UIScrollView.
  • PKDrawing is the data model responsible for storing all the drawings. PKCanvasView has a drawing property that’s used to get and set the data model.
  • PKToolPicker is the floating UI that consists of all the brushes, color palettes, and helper tools for the drawing.
  • PKTools holds the different kinds of brushes — which are essentially subclasses:
  1. PKEraserTool: This requires specifying either vector or bitmap as the type. Accordingly, the vector objects or pixels can be erased from the screen.
  2. PKInkingTool: These include pen, marker, andpencil for different kinds of sketches
  3. PKLassoTool is a selection tool for selecting a drawing area. It pops up a context menu that allows copy/paste and duplicating the selected drawing.

Here’s a look at the lasso tool in action on an iOS device.

It automatically detects the borders of a drawing and displays a context menu

The ToolPicker is a floating panel on regular-size classes (iPad devices), but it’s fixed to the bottom of the screen in the compact-size classes.

Also, the undo/redo and minimize buttons are not available in the compact version of ToolPicker.

The ToolPicker palette has a responder-based visibility. That means that it’s visible when the PKCanvasView is the firstResponder and can be hidden by resigning PKCanvasView from the first responder.

To enable/disable finger drawing with PencilKit, we can toggle the Boolean property allowsFingerDrawing on the PKCanvasView.

Enough talk. Let’s build our iOS application using PencilKit now.

Implementation

We’ll be implementing the following things in our iOS application.

  • Adding undo/redo draw actions for iOS devices
  • Saving drawing sketches to the photos library

Set Privacy — Photo Library Additions Usage Description to Allowed in Info.plist in order to save images.

Our Storyboard

Built-in selectors are set on the undo and redo buttons

For the undo and redo actions, we’ve used the built-in selectors.

Setting the Canvas View

The following code sets the Canvas View for you:

let canvasView = PKCanvasView(frame: .zero) canvasView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(canvasView)
NSLayoutConstraint.activate([ canvasView.topAnchor.constraint(equalTo: navigationBar.bottomAnchor), canvasView.bottomAnchor.constraint(equalTo: view.bottomAnchor), canvasView.leadingAnchor.constraint(equalTo: view.leadingAnchor), canvasView.trailingAnchor.constraint(equalTo: view.trailingAnchor), ])

Setting the ToolPicker

  • The initialization is done by asking for the shared ToolPicker for the window
  • Canvas View needs to be added as an observer to the ToolPicker
  • setVisible true indicates that whenever the Canvas View becomes the first responder, the palette will show up
guard let window = view.window, let toolPicker = PKToolPicker.shared(for: window) else { return }
toolPicker.setVisible(true, forFirstResponder: canvasView) toolPicker.addObserver(canvasView) 
canvasView.becomeFirstResponder()

Clear the Canvas View

In order to clear the PKCanvasView, just reinitialize the PKDrawing instance.

canvasView.drawing = PKDrawing()

Saving drawing to UIImage

func image(from rect: CGRect, scale: CGFloat) is invoked on the PKDrawing instance.

It returns a UIImage of the portion of the drawing, we want to capture. The scale is typically set to 1.0. Set higher values for a more detailed image (useful for retina display).

let image = canvasView.drawing.image(from: canvasView.drawing.bounds, scale: 1.0)
UIImageWriteToSavedPhotosAlbum(image, self, nil, nil)

Here’s the full source code of our PencilKit iOS 13 application:

Here’s an output of the PencilKit application in action on an iPhone device:

Screengrab from my iPhone

Conclusion

That sums up this introductory article on PencilKit in iOS 13. Now go draw and doodle with it.

You can download the full source code from our Github repository.

Next Part

Yes, we have a sequel! We’ll be implementing Core ML alongside PencilKit by using the famous MNIST model in the next part.

If you’ve come this far and liked this article, here’s another one you may like:

iOS
Programming
Software Development
Visual Design
Swift
Recommended from ReadMedium