PencilKit无法切换画笔及颜色,仅能绘制黑色的技术求助
代码实现
import UIKit import PencilKit import PhotosUI class ViewController: UIViewController, PKCanvasViewDelegate, PKToolPickerObserver { @IBOutlet weak var pencilButton: UIBarButtonItem! @IBOutlet weak var canvasView: PKCanvasView! let canvasWidth: CGFloat = 768 let canvasOverScrollHeight: CGFloat = 500 let drawing = PKDrawing() override func viewDidLoad() { super.viewDidLoad() canvasView.drawing = drawing canvasView.delegate = self canvasView.alwaysBounceVertical = true canvasView.drawingPolicy = .anyInput } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let toolPicker = PKToolPicker() toolPicker.setVisible(true, forFirstResponder: canvasView) toolPicker.addObserver(canvasView) canvasView.becomeFirstResponder() } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() let canvasScale = canvasView.bounds.width / canvasWidth canvasView.minimumZoomScale = canvasScale canvasView.maximumZoomScale = canvasScale canvasView.zoomScale = canvasScale updateContentSizeForDrawing() canvasView.contentOffset = CGPoint(x: 0, y: -canvasView.adjustedContentInset.top) } override var prefersHomeIndicatorAutoHidden: Bool{ return true } @IBAction func fingerOrPencil (_ sender: Any) { canvasView.allowsFingerDrawing.toggle() pencilButton.title = canvasView.allowsFingerDrawing ? "Finger" : "Pencil" } @IBAction func saveToCameraRoll(_ sender: Any) { UIGraphicsBeginImageContextWithOptions(canvasView.bounds.size, false, UIScreen.main.scale) canvasView.drawHierarchy(in: canvasView.bounds, afterScreenUpdates: true) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() if image != nil { PHPhotoLibrary.shared().performChanges({ PHAssetChangeRequest.creationRequestForAsset(from: image!) }, completionHandler: {success, error in }) } } func updateContentSizeForDrawing() { let drawing = canvasView.drawing let contentHeight: CGFloat if !drawing.bounds.isNull { contentHeight = max(canvasView.bounds.height, (drawing.bounds.maxY + self.canvasOverScrollHeight) * canvasView.zoomScale) } else { contentHeight = canvasView.bounds.height } canvasView.contentSize = CGSize(width: canvasWidth * canvasView.zoomScale, height: contentHeight) } // Delegate Methods func canvasViewDrawingDidChange(_ canvasView: PKCanvasView) { updateContentSizeForDrawing() } func canvasViewDidEndUsingTool(_ canvasView: PKCanvasView) { } func canvasViewDidFinishRendering(_ canvasView: PKCanvasView) { } func canvasViewDidBeginUsingTool(_ canvasView: PKCanvasView) { } }
控制台输出
2023-01-04 18:34:04.429420+0300 Drawing[45460:449613] [断言] UINavigationBar为UINavigationController解码为未锁定状态,或navigationBar代理设置错误,配置不一致可能导致问题。navigationController=<UINavigationController: 0x123024000>, navigationBar=<UINavigationBar: 0x12140a0a0; frame = (0 47; 0 50); opaque = NO; autoresize = W; layer = <CALayer: 0x6000030afae0>> delegate=0x123024000
2023-01-04 18:34:04.468831+0300 Drawing[45460:449613] Metal API验证已启用
2023-01-04 18:34:04.705019+0300 Drawing[45460:449613] [ToolPicker]缺少用于恢复PKPaletteNamedDefaults状态的默认字典
2023-01-04 18:35:00.196200+0300 Drawing[45460:449613] 键盘无法呈现视图控制器(尝试呈现<UIColorPickerViewController: 0x121846e00>)
解决方案
1. 修复ToolPicker初始化方式
问题核心在于手动实例化PKToolPicker(),而非使用系统共享的工具选择器。共享实例能正确关联系统颜色选择器和画笔配置,手动创建的实例无法正常弹出颜色选择器,导致只能使用默认黑色。
修改viewDidAppear方法:
override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) guard let toolPicker = PKToolPicker.shared(for: canvasView.window!) else { return } toolPicker.setVisible(true, forFirstResponder: canvasView) toolPicker.addObserver(self) toolPicker.addObserver(canvasView) canvasView.becomeFirstResponder() }
2. 补充ToolPickerObserver必要方法(可选)
既然ViewController实现了PKToolPickerObserver,添加以下方法确保工具配置变更能被正确响应:
func toolPickerSelectedToolDidChange(_ toolPicker: PKToolPicker) { // 可选:工具切换时的自定义逻辑 } func toolPickerVisibilityDidChange(_ toolPicker: PKToolPicker) { // 可选:工具选择器显示/隐藏时的自定义逻辑 }
3. 处理其他控制台警告
- NavigationBar断言警告:检查Storyboard中UINavigationController的配置,确保NavigationBar代理未被错误修改;若不需要自定义导航栏行为,可在
viewDidLoad中添加navigationController?.navigationBar.delegate = nil。 - PKPaletteNamedDefaults警告:在
viewDidLoad中初始化默认调色板解决:if PKPalette.shared(named: .standard) == nil { _ = PKPalette.shared(named: .standard, createIfNecessary: true) }
内容的提问来源于stack exchange,提问作者asduskun

