Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2020 SwiftUI & UI Frameworks

WWDC20 · 14 min · SwiftUI & UI Frameworks

Meet Scribble for iPad

Scribble offers a lightweight, ergonomic, and enjoyable way of entering text on iPad with Apple Pencil. Discover how people can take advantage of Scribble and handwritten text in apps that use standard text input controls or that implement a custom text editing experience. You’ll learn how it integrates into TextKit, and when you’ll need to adopt the new UIScribbleInteraction and UIIndirectScribbleInteraction APIs to provide a delightful and consistent experience with Scribble in your app. To get the most out of this session, you should be familiar with UIKit text input controls, as well as keyboard input technologies. To get started, watch “Keyboard Input in iOS”. If you’re building a custom text editor, you should be familiar with the UITextInput protocol, TextKit, and related text input APIs. For more information, we recommend checking out “TextKit Best Practices” and “The Keys to a Better Text Input Experience.” And for design guidelines on pencil-based interaction, check out “Apple Pencil Design Essentials.”

Watch at developer.apple.com ↗

Transcript all transcripts

Code shown on screen · 9 snippets

isHandlingWriting Example swift · at 9:15 ↗
func updateSearchCompletion() {
    customSearchField.hideCompletionText = interaction.isHandlingWriting
}
UIScribbleInteraction.isPencilInputExpected swift · at 9:35 ↗
override func viewDidAppear(_ animated: Bool) {
    if UIScribbleInteraction.isPencilInputExpected {
        let lineHeight = textField.font?.lineHeight ?? 17.0
        let heightForScribble = lineHeight * 4.0
        heightConstraint.constant = heightForScribble
    }
}
scribbleInteractionDidFinishWriting swift · at 9:51 ↗
func scribbleInteractionDidFinishWriting(_ interaction: UIScribbleInteraction) {
    let lineHeight = textField.font?.lineHeight ?? 17.0
    let heightForScribble = lineHeight * 4.0
    heightConstraint.constant = heightForScribble
}
Should Begin swift · at 10:08 ↗
func scribbleInteraction(_ interaction: UIScribbleInteraction,
                         shouldBeginAt location: CGPoint) -> Bool {
    return !appIsInDrawingMode()
}
Install UIIndirectScribbleInteraction in Engraving Field swift · at 11:41 ↗
override init(frame: CGRect) {
    super.init(frame: frame)
    indirectScribbleInteraction = UIIndirectScribbleInteraction(delegate: self)
    addInteraction(indirectScribbleInteraction)
    ...
}
Request Elements swift · at 11:48 ↗
func indirectScribbleInteraction(_ interaction: UIInteraction,
                                 requestElementsIn rect: CGRect,
                                 completion: @escaping ([ElementIdentifier]) -> Void) {
    completion(["EngravingIdentifier"])
}
Frame for element swift · at 12:14 ↗
func indirectScribbleInteraction(_ interaction: UIInteraction,
                                 frameForElement elementIdentifier: String) -> CGRect {
    return bounds
}
Focus Element if Needed swift · at 12:28 ↗
func indirectScribbleInteraction(_ interaction: UIInteraction,
                                 focusElementIfNeeded elementIdentifier: String,
                                 referencePoint focusReferencePoint: CGPoint,
                                 completion: @escaping ((UIResponder & UITextInput)?) -> Void)
{
    if editingTextField == nil {
        createTextField()
    }
    editingTextField?.becomeFirstResponder()
    
    completion(editingTextField)
}
Is Element Focused swift · at 12:57 ↗
func indirectScribbleInteraction(_ interaction: UIInteraction,
                                 isElementFocused elementIdentifier: String) -> Bool {
    // Indicate if our only element is currently installed and focused
    return editingTextField?.isFirstResponder ?? false
}

Resources