PKToolPicker из PencilKit не отображается в программно созданном UIWindow
У меня есть контроллер представления, который хочет показать PKCanvasView
и PKToolPicker
из PencilKit. Вот код:
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 {
}
Моя проблема в том, что когда я программно запускаю ViewController
как начальный ViewController в раскадровке, PKToolPicker
отлично себя показывает в нижней части экрана. Вот скриншот рабочегоDrawingViewController
Однако, если я запускаю программно ViewController
с новым UIWindow
. затемPKToolPicker
не показывать.
Итак, я предполагаю, что с моим ViewController
код. Что это может быть проблема с тем, как я создаю новый UIWindow.
Я создаю окно со следующим кодом (обратите внимание, что я работаю с iOS 13) из 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
}
Я очень озадачен. PencilKit не дает особых предупреждений или ошибок относительно того, почему он не отображает PKToolPicker. Любой вклад приветствуется.
Редактировать 1
Просто добавляю больше информации. Я посмотрел на средство просмотра иерархии, и похоже, что PKToolPicker есть, но ни один из инструментов не отображается на экране.
Редактировать 2
Я добавил таймер в ViewController
, и я заметил, что когда PKToolPicker
действительно показано, PKCanvasView
фактически становится первым респондентом. Не сразу, а через несколько секунд. Когда я использую программно созданныйUIWindow
, PKCanvasView
никогда не становится первым респондентом. Так что, возможно, это связано с тем, что мое окно каким-то образом не просит быть первым респондентом.
Редактировать 3
Мне удалось упростить задачу и поместить ее в пример приложения, которое вы можете проверить здесь. Если вы посмотрите вSceneDelegate.swift
, там есть код для создания моего собственного окна. Если я закомментирую этот код, я увижу свой инструмент для выбора без проблем. Когда я раскомментировал код, он не показывает средство выбора инструментов.
1 ответ
Сегодня я просто играл с тем же API и столкнулся с той же проблемой. Я думаю, что проблема в создании вашего окна в делегате сцены, вам не хватает:window.makeKeyAndVisible()
Это плюс удаление ссылки на раскадровку в вашем Info.plist, поскольку вы вручную загружаете ее в делегат сцены. Просто удалите ключUISceneStoryboardFile
внутри UIApplicationSceneManifest
Я думаю, проблема в том, что ОС создает ваше окно для вас (на основе Info.plist), но затем вы заменяете это окно своим собственным созданным вручную. На окно, которое фактически отображается (созданное Info.plist), больше нельзя ссылаться.