PencilKit toolPicker is not showing up

I am trying to create an app using PencilKit. I have the following code in one of my ViewControllers.


```

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard
let window = view.window,
let toolPicker = PKToolPicker.shared(for: window) else { return }
toolPicker.setVisible(true, forFirstResponder: canvasView)
toolPicker.addObserver(canvasView)
canvasView.becomeFirstResponder()
}

```


Although I am calling the

setVisible
function and making the
canvasView
the firstResponder, my
toolPicker
is not showing up, and printing
toolPicker.isVisible
is false.

Replies

Where and how do you define canvasView ?


Did you add it to view ?


I think you should have:


override func viewDidAppear(_ animated: Bool) {
  super.viewDidAppear(animated)

    let canvasView = PKCanvasView(frame: self.view.bounds)
  guard
  let window = view.window,
  let toolPicker = PKToolPicker.shared(for: window) else { return }

  toolPicker.setVisible(true, forFirstResponder: canvasView)
  toolPicker.addObserver(canvasView)
  canvasView.becomeFirstResponder()
  view.addSubview(canvasView)
}

canvasView is initalized in viewDidLoad:


canvasView = PKCanvasView(frame: view.bounds)

And did you add it as subview ?

Yep, I just copied and pasted your version of the code, and it's still not showing up. I can draw on the canvas. It's just there's no toolPicker.

I tested on simulator, this exact code:


import PencilKit


     override func viewDidAppear(_ animated: Bool) {
         
          super.viewDidAppear(animated) // Manquait
          setTempData()
          if #available(iOS 13.0, *) {
               let canvasView = PKCanvasView(frame: self.view.bounds)
               guard
               let window = view.window,
               let toolPicker = PKToolPicker.shared(for: window) else { return }
              
               toolPicker.setVisible(true, forFirstResponder: canvasView)
               toolPicker.addObserver(canvasView)
               canvasView.becomeFirstResponder()
               view.addSubview(canvasView)
          } else {
               // Fallback on earlier versions
          }
     }


works "well": I mean I see the pens at the bottom.


Added

               print(toolPicker.isVisible)


and get true in log

I just copied and pasted this exact code aside from the setTempData, and I don't see the pens at the bottom.

Yes, I really copied so setTempData() was superfluous !


Do you run on device or simulator ?


Which iOS version (iOS 13 required)

I'm running it on a simulator. It is iOS 13.

If you want, you can post an email address for a minute, so that we can share files.

I don't really feel comfortable giving my email address, but the project should be accessible on my Github: https://github.com/druvinskiy/InstaKids under the Firebrase branch.

I could not run your code, I miss JGProgressHUD.


But I noticed your code is not exactly the same I proposed:


you have:


    override func viewDidLoad() {
        super.viewDidLoad()
       
        setNavigationBar()
       
        let canvasView = PKCanvasView(frame: view.bounds)
        self.canvasView = canvasView
        canvasView.allowsFingerDrawing = true
        view.addSubview(canvasView)
       
        if let sketch = sketch {
            SketchService.downloadData(from: sketch.drawingUrl!) { (data) in
                self.canvasView.drawing = try! PKDrawing(data: data)
                canvasView.delegate = self
                self.saveButton.isEnabled = false
            }
        }
       
        canvasView.delegate = self
        saveButton.isEnabled = false
       
        canvasView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(canvasView)
       
        canvasView.backgroundColor = .offWhite
       
        setupToolPicker()
    }

and


    func setupToolPicker() {
        if let window = self.parent?.view.window,
            let toolPicker = PKToolPicker.shared(for: window) {
            toolPicker.setVisible(true, forFirstResponder: canvasView)
            toolPicker.addObserver(canvasView)
            canvasView.becomeFirstResponder()
            toolPicker.addObserver(self)
            updateTools(toolPicker)
        }
    }



In my case:

     override func viewDidAppear(_ animated: Bool) { 
          
          super.viewDidAppear(animated) // Manquait 
          setTempData() 
          if #available(iOS 13.0, *) { 
               let canvasView = PKCanvasView(frame: self.view.bounds) 
               guard 
               let window = view.window, 
               let toolPicker = PKToolPicker.shared(for: window) else { return } 
               
               toolPicker.setVisible(true, forFirstResponder: canvasView) 
               toolPicker.addObserver(canvasView) 
               canvasView.becomeFirstResponder() 
               view.addSubview(canvasView) 
          } else { 
               // Fallback on earlier versions 
          } 
     }



So, your window is:

self.parent?.view.window

in my case:

view.window


Why calling parent ?

Are you sure it is not nil ?

I'm having probably the same problem. I followed this tutorial https://medium.com/better-programming/an-introduction-to-pencilkit-in-ios-4d40aa62ba5b


In a new project, it works fine. But in my existing project, I can draw, but I can't see the tool palet. Anyone have any ideas what might cause the palet to not appear?

What does calling toolPicker.isVisible return? Since you have made the canvasView influence the tool picker's visibility with toolPicker.setVisible(true, forFirstResponder: canvasView) anytime the canvasView is not the first responder, the tool picker will hide. Verify that canvasView.isFirstResponder is true.
我在iOS13上遇到了这个问题,最后我的解决办法是去掉了Main.storyboard文件,并且将Info里面相关的配置字段去掉了,最终toolPicker能正常展示出来了。

iOS 14.5

import UIKit
import PencilKit

class DrawingCanvasViewController: UIViewController {

    lazy var canvasView: PKCanvasView = {
       let canvasView = PKCanvasView()
        canvasView.drawingPolicy = .anyInput
        canvasView.translatesAutoresizingMaskIntoConstraints = false
        return canvasView
    }()

    lazy var toolPicker: PKToolPicker = {
       let toolPicker = PKToolPicker()
        toolPicker.addObserver(self)
        return toolPicker
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(canvasView)
        canvasView.frame = view.bounds
        toolPicker.setVisible(true, forFirstResponder: canvasView)
        toolPicker.addObserver(canvasView)
        canvasView.delegate = self
        canvasView.becomeFirstResponder()
    }
}

extension DrawingCanvasViewController: PKToolPickerObserver, PKCanvasViewDelegate {
}

The thing was here:

    lazy var toolPicker: PKToolPicker = {
       let toolPicker = PKToolPicker()
        toolPicker.addObserver(self)
        return toolPicker
    }()

You need to make the tool picker lazy var and add observer to itself. Thanks to Recoding Channel on Youtube Nice tutorial https://youtu.be/f2SHsHsjTGM