0

I am having two issues using PKToolPicker with SwiftUI. The first issue is that once I draw on the canvas view, toggling the visibility of the PKToolPicker doesn't make it go away. The second issue is that sometimes the PKToolPicker doesn't go away when dismissing the view. Here is my code:

struct CanvasView: UIViewRepresentable {
  final class Coordinator: NSObject {
    @Binding var canvasView: PKCanvasView

    let canvasDidChange: (PKCanvasView) -> Void
    let picker: PKToolPicker

    init(
      canvasView: Binding<PKCanvasView>,
      canvasDidChange: @escaping (PKCanvasView) -> Void,
      picker: PKToolPicker
    ) {
      _canvasView = canvasView
      self.canvasDidChange = canvasDidChange
      self.picker = picker
    }

    deinit {
      picker.setVisible(false, forFirstResponder: canvasView)
      picker.removeObserver(canvasView)
    }
  }

  @Binding var canvasView: PKCanvasView
  @Binding var showToolPicker: Bool

  let canvasDidChange: (PKCanvasView) -> Void

  let picker = PKToolPicker()

  func makeCoordinator() -> Coordinator {
    Coordinator(canvasView: $canvasView, canvasDidChange: canvasDidChange, picker: picker)
  }

  func makeUIView(context: Context) -> some UIView {
    canvasView.tool = PKInkingTool(.pen, color: .black, width: 10)
    #if targetEnvironment(simulator)
    canvasView.drawingPolicy = .anyInput
    #endif
    canvasView.delegate = context.coordinator
    picker.addObserver(canvasView)
    canvasView.becomeFirstResponder()
    return canvasView
  }

  func updateUIView(_ uiView: UIViewType, context: Context) {
    picker.setVisible(showToolPicker, forFirstResponder: canvasView)
  }
}

I've verified that updateUIView is called when changing showToolPicker and that showToolPicker has the correct value. Unfortunately, once I draw on the canvas showToolPicker being true or false does make it go away. Further, if showToolPicker is false, it appears as though the PKToolPicker is no longer attached to the canvas view and changing the pen tool in the PKToolPicker has no effect.

Am I doing something wrong here or is this a SwiftUI/PencilKit bug?

Jake
  • 13,097
  • 9
  • 44
  • 73

1 Answers1

0

I wasn't able to change the visibility of the tool picker after the canvas had been drawn on; however, moving the some of the tool picker logic to onAppear and onDisappear solved the issue with the tool picker continuing to show after dismissing the view. Here are the main changes:

private final class DrawingManager: ObservableObject {
  let toolPicker = PKToolPicker()
  var canvasView: PKCanvasView?

  func register(_ canvasView: PKCanvasView) {
    self.canvasView = canvasView
    toolPicker.setVisible(true, forFirstResponder: canvasView)
    toolPicker.addObserver(canvasView)
  }

  func unregister() {
    guard let canvasView else {
      return
    }
    toolPicker.setVisible(false, forFirstResponder: canvasView)
    toolPicker.removeObserver(canvasView)
    self.canvasView = nil
  }
}

struct DrawingView: View {
  ...
 
  @StateObject private var drawingManager = DrawingManager()
  @State private var canvasView = PKCanvasView()

  ...

  var body: some View {
    <VIEW CODE>
      .onAppear {
        drawingManager.register(canvasView)
      }
      .onDisappear {
        drawingManager.unregister()
      }
    }
  }
Jake
  • 13,097
  • 9
  • 44
  • 73