无法切换PKToolPicker工具:PencilKit绘图工具切换异常求助
解决PencilKit PKToolPicker无法切换工具的问题
问题根源
你这段代码里有几个关键问题,导致工具切换失效:
- 每次点击按钮都会新建PKToolPicker实例,旧的picker直接被丢弃,无法保留工具选择状态
- 未将PKToolPicker保存为类属性,实例用完就被释放,无法和PKCanvasView正常交互
- 没有将ViewController设置为PKToolPicker的观察者,接收不到工具变化的通知
修复后的完整代码
class ViewController: UIViewController, PKToolPickerObserver { private var canvasView: PKCanvasView! private var toolPicker: PKToolPicker! // 持久保存picker引用,避免重复创建 @IBOutlet weak var imgView: UIImageView! override func viewDidLoad() { super.viewDidLoad() setupNavigationButton() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) setupCanvasView() setupImageFromDocuments() } private func setupNavigationButton() { let pencilButton = UIButton(frame: CGRect(x: 0, y: 0, width: 50, height: 50)) pencilButton.addTarget(self, action: #selector(showPKToolKit), for: .touchUpInside) pencilButton.setImage(UIImage(systemName: "pencil.tip"), for: .normal) pencilButton.tintColor = .tintColor navigationItem?.rightBarButtonItem = UIBarButtonItem(customView: pencilButton) } private func setupCanvasView() { canvasView = PKCanvasView(frame: imgView.bounds) canvasView.isOpaque = false canvasView.drawingPolicy = .anyInput // 提前设置绘图策略 // 将canvas添加到imgView上层,确保绘制内容显示在图片之上 imgView.addSubview(canvasView) // 使用Auto Layout替代固定frame,适配屏幕旋转与不同尺寸 canvasView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ canvasView.topAnchor.constraint(equalTo: imgView.topAnchor), canvasView.leadingAnchor.constraint(equalTo: imgView.leadingAnchor), canvasView.trailingAnchor.constraint(equalTo: imgView.trailingAnchor), canvasView.bottomAnchor.constraint(equalTo: imgView.bottomAnchor) ]) // 使用全局共享的PKToolPicker实例,而非每次新建 toolPicker = PKToolPicker.shared() toolPicker.addObserver(self) toolPicker.addObserver(canvasView) } private func setupImageFromDocuments() { let fileManager = FileManager.default guard let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return } do { let urls = try fileManager.contentsOfDirectory(at: documentsURL, includingPropertiesForKeys: nil) guard !urls.isEmpty else { print("Documents目录为空") return } let data = try Data(contentsOf: urls[0]) imgView.image = UIImage(data: data) } catch { print("加载图片失败: \(error.localizedDescription)") } } @objc func showPKToolKit() { canvasView.becomeFirstResponder() toolPicker.setVisible(true, forFirstResponder: canvasView) toolPicker.reloadAllTools() // 确保工具列表正常加载 } // 可选:监听工具切换事件,自定义后续逻辑 func toolPickerSelectedToolDidChange(_ toolPicker: PKToolPicker) { // 这里可以添加工具切换后的处理代码 } }
关键修改说明
- 添加持久化
toolPicker属性:使用PKToolPicker.shared()获取全局实例,避免重复创建,保证工具选择状态的连贯性 - 提前初始化Canvas与Picker关联:在
viewDidAppear中完成canvas和picker的绑定,而非点击按钮时才临时创建 - 调整Canvas层级与适配方式:将canvas添加到imgView上层确保绘制内容可见,用Auto Layout替代固定frame,适配不同屏幕场景
- 正确设置观察者:将ViewController和CanvasView都添加为picker的观察者,保证交互逻辑正常运行
- 提前配置绘图策略:在canvas初始化阶段就设置
drawingPolicy,无需在点击按钮时重复操作
内容的提问来源于stack exchange,提问作者Gopalakrishnan G.S.R
相关产品推荐
相关产品推荐

