Apple Pencil touchesEstimatedPropertiesUpdated延迟问题求助
Apple Pencil
touchesEstimatedPropertiesUpdated 延迟异常(手指误触场景) 问题描述
开发绘图应用时,使用touchesEstimatedPropertiesUpdated获取Apple Pencil的精准压力数据,正常状态下该函数在touchesMoved触发后约0.05秒更新,延迟符合预期。但当存在手指触碰并滑动屏幕(多为绘图时手背误触)的情况时,延迟会增至1秒甚至更久。
已尝试的排查措施:
- 禁用视图的多点触控
- 使用设置
allowedTouchTypes为.pencil的手势识别器 - 确保手指触碰与Apple Pencil触碰不在同一视图
- 通过Instruments检测未发现主线程阻塞
测试环境:
- iPad第6代
- Apple Pencil第1代
- iPadOS 16.4.1
相关代码
class CanvasView: UIView { override func touchesEstimatedPropertiesUpdated(_ touches: Set<UITouch>) { for touch in touches { if(touch.estimatedPropertiesExpectingUpdates.isEmpty) { let lag = ProcessInfo.processInfo.systemUptime - touch.timestamp NSLog("lag: \(lag)") } } } }
可能的原因与解决方案
1. 系统触摸资源抢占
iPadOS在处理多触摸输入时,会优先响应手指触发的系统级手势(如滑动、缩放),导致Apple Pencil的预估属性更新队列被延迟。即便设置了allowedTouchTypes,底层触摸处理资源仍可能被无关触摸占用。
解决措施:
- 在触摸事件回调中直接过滤非Apple Pencil的触摸,避免无关事件占用处理链路:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesBegan(touches.filter { $0.type == .pencil }, with: event) } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesMoved(touches.filter { $0.type == .pencil }, with: event) } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesEnded(touches.filter { $0.type == .pencil }, with: event) } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesCancelled(touches.filter { $0.type == .pencil }, with: event) }
2. Apple Pencil第1代硬件限制
Apple Pencil第1代通过Lightning接口配对,数据传输速率低于第2代。多触摸场景下,硬件层面的数据处理可能出现瓶颈,导致预估属性更新延迟。
验证方式:
- 在支持Apple Pencil第2代的iPad Pro上复现问题,若延迟消失,则大概率是Pencil 1代的硬件限制。
3. iPadOS版本潜在Bug
iPadOS 16.4.1可能存在多触摸场景下的Pencil触摸处理Bug。
解决措施:
- 升级至最新iPadOS版本测试问题是否消失;也可降级至更早的稳定版本(如16.3)验证是否为版本导致的问题。
4. 触摸事件线程优化
尽管主线程无阻塞,但底层触摸处理线程可能存在资源竞争。可将Pencil触摸数据的计算逻辑移至后台线程,仅UI更新回到主线程,减少主线程触摸处理压力:
override func touchesEstimatedPropertiesUpdated(_ touches: Set<UITouch>) { DispatchQueue.global(qos: .userInitiated).async { for touch in touches { guard touch.type == .pencil, touch.estimatedPropertiesExpectingUpdates.isEmpty else { continue } let lag = ProcessInfo.processInfo.systemUptime - touch.timestamp NSLog("lag: \(lag)") // 绘图UI更新需回到主线程 DispatchQueue.main.async { // 执行绘图逻辑 } } } }
内容的提问来源于stack exchange,提问作者WeirdHat
相关产品推荐
相关产品推荐

