I am trying to use PKToolPicker
from PencilKit (iOS/Swift) from a custom view (which is NOT PKCanvasView). The custom view conforms to PKToolPickerObserver
. Everything works fine during compile time but I never get to see the PKToolPicker! If I replace my custom view with PKCanvasView, everything works fine!
I am doing this in SwiftUI with UIViewRepresentable (thus First Responder seems a mystery!).
Here is the SwiftUI view in question:
struct PencilKitView: UIViewRepresentable {
typealias UIViewType = myView
let coordinator = Coordinator()
class Coordinator: NSObject, PKToolPickerObserver {
func toolPickerSelectedToolDidChange(_ toolPicker: PKToolPicker) {
// some code
}
func toolPickerVisibilityDidChange(_ toolPicker: PKToolPicker) {
// some code
}
}
func makeCoordinator() -> PencilKitView.Coordinator {
return Coordinator()
}
func makeUIView(context: Context) -> myView {
let canvasView = myView()
canvasView.isOpaque = false
canvasView.backgroundColor = UIColor.clear
canvasView.becomeFirstResponder()
if let window = UIApplication.shared.windows.filter({$0.isKeyWindow}).first,
let toolPicker = PKToolPicker.shared(for: window) {
toolPicker.addObserver(canvasView)
toolPicker.addObserver(coordinator)
toolPicker.setVisible(true, forFirstResponder: canvasView)
}
return canvasView
}
func updateUIView(_ uiView: myView, context: Context) {
}
}
If I replace myView
with PKCanvasView
above, the PKToolPicker will be seen.
For the sake of completeness, here is the MyView stub:
class myView: UIScrollView, PKToolPickerObserver {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
public func toolPickerVisibilityDidChange(_ toolPicker: PKToolPicker) {
/// some code
}
public func toolPickerSelectedToolDidChange(_ toolPicker: PKToolPicker) {
/// some code
}
public func toolPickerIsRulerActiveDidChange(_ toolPicker: PKToolPicker) {
/// some code
}
public func toolPickerFramesObscuredDidChange(_ toolPicker: PKToolPicker) {
/// some code
}
}
Anyone has succeeded in doing this? Is there some undocumented requirement for adopting PKToolPicker?
Here is simplest demo to show PKToolPicker for any custom UIView in SwiftUI.
Tested with Xcode 11.4 / iOS 13.4
struct ToolPickerDemo: View {
@State private var showPicker = false
var body: some View {
Button("Picker") { self.showPicker.toggle() }
.background(ToolPickerHelper(isActive: $showPicker))
}
}
class PickerHelperView: UIView {
override var canBecomeFirstResponder: Bool { true }
}
struct ToolPickerHelper: UIViewRepresentable {
@Binding var isActive: Bool
func makeUIView(context: Context) -> PickerHelperView {
PickerHelperView()
}
func updateUIView(_ uiView: PickerHelperView, context: Context) {
guard let window = uiView.window else { return }
let picker = PKToolPicker.shared(for: window)
picker?.setVisible(isActive, forFirstResponder: uiView)
DispatchQueue.main.async {
uiView.becomeFirstResponder()
}
}
}