Last week's introduction of the new iPad Pro brought us some fantastic improvements to the Apple Pencil. One of those improvements was the ability for the Apple Pencil to recognize simple gestures. Today we'll look at how to work these in our code. Let's dive in! 🏊♀️
First, let's cover the new system-level options for Apple Pencil. If we pair an Apple Pencil with our new iPad Pro by attaching it to the new magnetic inductive charger on the edge, we'll see a new item in our Settings.app for the Pencil.
Apple has provided a way for us to read these settings inside our own apps. This is through the UIPencilInteraction
class's preferredTapAction
class variable. This returns an enum
representing the user's current selection for how the double-tap Pencil gesture should behave.
Apple recommends we make the default behavior of our apps match whatever the user has selected in Settings.app.
We'll begin by setting our view controller as the delegate
of a new UIPencilInteraction
object, then adding that new interaction object to our view controller's view.
class ViewController: UIViewController, UIPencilInteractionDelegate {
init() {
super.init(nibName: nil, bundle: nil)
let pencilInteraction = UIPencilInteraction()
pencilInteraction.delegate = self
view.addInteraction(pencilInteraction)
}
// ...
}
Then, we'll implement UIPencilInteractionDelegate
's one function: pencilInteractionDidTap(_:)
:
class ViewController: UIViewController, UIPencilInteractionDelegate {
// ...
// UIPencilInteractionDelegate
public func pencilInteractionDidTap(_ interaction: UIPencilInteraction) {
print("pencil double tapped!")
}
// ...
}
That function will be called anytime the user double-taps on their Pencil. Neat!
Next, we'll add some handling for the system setting:
public func pencilInteractionDidTap(_ interaction: UIPencilInteraction) {
switch UIPencilInteraction.preferredTapAction {
case .ignore: return
case .showColorPalette: showColorPallet()
case .switchEraser: change(tool: .eraser)
case .switchPrevious: changeToPreviousTool()
}
}
Some apps don't have tools like erasers though, and some apps might not have "tools" at all. In these cases, we can define our own behavior to respond to a double-tap on the Pencil.
In our case we'd like to support both system and custom actions.
We'll add a preference (stored in UserDefaults
) to our app for our users to optionally choose to ignore the system double-tap behavior, and add a guard
statement to our function to look for it:
public func pencilInteractionDidTap(_ interaction: UIPencilInteraction) {
guard UserDefaults.standard.bool(forKey: "customPencilActionsEnabled") == false else {
doSomethingCustom()
return
}
switch UIPencilInteraction.preferredTapAction {
case .ignore: return
case .showColorPalette: showColorPallet()
case .switchEraser: change(tool: .eraser)
case .switchPrevious: changeToPreviousTool()
}
}
That's all for now, have a question or idea for a Bite? Send it to hello@littlebitesofcocoa.com.