I have a view controller that wants to show a PKCanvasView
and a PKToolPicker
from PencilKit. Here's the code:
import UIKit
import PencilKit
class ViewController: UIViewController {
@IBOutlet weak var canvas: PKCanvasView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
canvas.backgroundColor = .lightGray
canvas.allowsFingerDrawing = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// self.showPicker()
self.perform(#selector(showPicker), with: self, afterDelay: 0)
}
@objc private func showPicker() {
guard let window = UIApplication.shared.windows.filter({ $0.windowScene?.activationState == .foregroundActive }).first else {
return
}
let picker = PKToolPicker.shared(for: window)
if let picker = picker, picker.isVisible {
return
}
print("Picker not visible")
picker?.setVisible(true, forFirstResponder: canvas)
picker?.addObserver(canvas)
picker?.addObserver(self)
canvas.becomeFirstResponder()
self.perform(#selector(showPicker), with: self, afterDelay: 0.5)
}
}
extension ViewController: PKToolPickerObserver {
}
My problem is, when I programmatically launch ViewController
as the initial ViewController in the storyboard, the PKToolPicker
shows itself just fine at the bottom of the screen. Here's a screenshot of a working DrawingViewController
However, if i programmatically launch ViewController
with a new UIWindow
. then the PKToolPicker
does not show.
So I'm assuming that there isn't anything wrong with my ViewController
code. That it might be an issue with how I create a new UIWindow.
I create the window with the following code (note I'm working with iOS 13) from SceneDelegate.swift
:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let windowScene = (scene as? UIWindowScene) else { return }
let window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window.windowScene = windowScene
window.rootViewController = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(withIdentifier: "ViewController")
self.window = window
}
I'm pretty stumped. PencilKit doesn't give much in the way of warnings or errors as to why it fails to show the PKToolPicker. Any input is appreciated.
Edit 1
Just adding more information. I looked at the hierarchy viewer, and It looks like The PKToolPicker is there, but none of the tools are drawn to screen.
Edit 2
I added a timer in the ViewController
, and I noticed that when the PKToolPicker
is actually shown, the PKCanvasView
actually becomes the first responder. Not immediately, but after a few seconds. When I use a programmatically created UIWindow
, PKCanvasView
never becomes the first responder. So maybe it has to do with the fact that my window isn't asking to be the first responder in some way.
Edit 3
I've managed to simplify the problem and put it into a sample app which you can checkout here. If you look in SceneDelegate.swift
, there's code in there to create my own window. If I comment this code out, I see my tool picker without issue. When I uncommented the code, it doesn't show the tool picker.