You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PencilKit无法切换画笔及颜色,仅能绘制黑色的技术求助

问题: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 19:55:13