我有一个自定义的NSView子类,它被用作我的项目https://github.com/torchie/TrackKit中的子视图。它检测NSTouches并收集它们的物理数据,然后在其drawRect的详细模式方法中绘制这些数据。同时,SpriteKit场景呈现它呈现的内容。
但是,当我在内置触控板上移动手指时,暂停SpriteKit视图中的所有渲染,直到触摸再次静止为止。 Magic Trackpad,有一个帧率下降,但渲染并没有完全停止。在这两种情况下,子视图TKDetectorView继续渲染触摸点。
有问题的touchesMoved方法:
-(void)touchesMovedWithEvent:(NSEvent *)event {
for(NSTouch* touch in [event touchesMatchingPhase:NSTouchPhaseAny inView:self]) {
[touch_identities setObject:touch forKey:[touch identity]];
}
[self phys_record];
if(![self needsDisplay]) {
[self setNeedsDisplay:YES];
}
}
来自详细模式函数断点的数据,其中我同时触摸了内置触控板(#0)和Magic Trackpad(#1):
touch_identities __NSDictionaryM * 2 key/value pairs 0x0000608000055bd0
[0] (null) (no summary) : (no summary)
key NSConcreteValue * 0x600000054b80 0x0000600000054b80
value NSTouch * 0x6000000b2480 0x00006000000b2480
NSObject NSObject
_index NSInteger 10 10
_identity NSConcreteValue * 0x600000054b80 0x0000600000054b80
_phase NSTouchPhase 2 2
_normalizedPosition NSPoint (x=0.4923553466796875, y=0.4602508544921875)
x CGFloat 0.4923553466796875 0.4923553466796875
y CGFloat 0.4602508544921875 0.4602508544921875
_privateFlags NSInteger 0 0
_view TKDetectorView * 0x6000001ff900 0x00006000001ff900
_device NSObject * 0x600000013300 0x0000600000013300
_deviceSize NSSize (width=368.50393709999997, height=311.81102370000002)
previous_positions NSMutableArray * nil 0x0000000000000000
_isResting BOOL YES '\xad'
[1] (null) (no summary) : (no summary)
key NSConcreteValue * 0x60800005ea50 0x000060800005ea50
value NSTouch * 0x6080000b3740 0x00006080000b3740
NSObject NSObject
_index NSInteger 1 1
_identity NSConcreteValue * 0x60800005ea50 0x000060800005ea50
_phase NSTouchPhase 2 2
_normalizedPosition NSPoint (x=0.7928314208984375, y=0.3984222412109375)
_privateFlags NSInteger 0 0
_view TKDetectorView * 0x6000001ff900 0x00006000001ff900
_device NSObject * 0x600000014d70 0x0000600000014d70
_deviceSize NSSize (width=297.63779534999998, height=215.43307092000001)
previous_positions NSMutableArray * nil 0x0000000000000000
_isResting BOOL YES '\xad'
我认为这可能是SpriteKit渲染线程在手指移动时被位置数组的不断修改所打断的结果,但这无法解释为什么它只发生在内置的触控板上。 MacBook Air而不是外部Magic Trackpad。我发现设备之间的touchesMoved的解释没有相关的区别。
答案 0 :(得分:0)
原始假设:内置触控板的轮询率明显高于touchesMoved事件的魔术触控板,导致更多的drawRects并中断SpriteKit视图的绘制线程。
失败 - 为touchesMovedWithEvent调用的数量和setNeedsDisplay的drawRect调用数增加一个计数器,显示在同一时间段内置和Magic Trackpad之间的数量没有显着差异。
解决方案:
touchesMovedWithEvent在方法结束时为自定义视图调用setNeedsDisplay。
在touchesMovedWithEvent中消除setNeedsDisplay调用,而是在SpriteKit场景的更新方法中调用自定义视图的setNeedsDisplay,从而在“从上面”操作该子视图修复了问题。
TKMyScene:
-(void)update {
[detector setNeedsDisplay:YES];
}
而不是TKDetectorView
-(void)touchesMovedWithEvent {
[self setNeedsDisplay:YES];
}