在我的项目中有一个带有NSButton的窗口和一个NSView(它是其他视图的容器).单击该按钮可更改容器的子视图,如下所示:
[containerView replaceSubview:displayedSubview with:nextView];
添加到containerView的第一个子视图有一个基于视图的TableView(使用绑定)填充NSTableCellView子类的对象.
这个子类NSTableCellView有一个跟踪区域,当鼠标进入/离开单元格时,它允许我显示/隐藏按钮.
方法mouseEntered:和mouseExited:分别使用setAlphaValue:方法显示和隐藏_buttonInsideTableCellView.
跟踪区域在init方法中创建如下:
NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingActiveInActiveApp; _trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil];
updateTrackingAreas方法很简单:
- (void)updateTrackingAreas { [_buttonInsideTableCellView setAlphaValue:0.0]; [self removeTrackingArea:_trackingArea]; NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited|NSTrackingActiveInActiveApp; _trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil]; [self addTrackingArea:_trackingArea]; [super updateTrackingAreas]; }
问题
当程序启动时,一切都按预期工作:如果鼠标在单元格上,则显示其按钮.
但是在我将containerView的子视图更改为nextView并返回到第一个视图后,当替换子视图时,当应用程序变为活动状态(???)时,方法updateTrackingAreas开始被多次调用(2次或更多次)进入或离开trackingArea(???).
调用堆栈
如果我在updateTrackingAreas中放置一个断点,这是调用堆栈:
#0 0x0000000100019e33 in -[CustomTableCellView updateTrackingAreas] #1 0x00007fff8a1b24e4 in -[NSView(NSInternal) _updateTrackingAreas] () #2 0x00007fff894740b6 in __NSArrayEnumerate () #3 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #4 0x00007fff894740b6 in __NSArrayEnumerate () #5 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #6 0x00007fff894740b6 in __NSArrayEnumerate () #7 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #8 0x00007fff894740b6 in __NSArrayEnumerate () #9 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #10 0x00007fff8a1b36bd in -[NSScrollView _updateTrackingAreas] () #11 0x00007fff894740b6 in __NSArrayEnumerate () #12 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #13 0x00007fff894740b6 in __NSArrayEnumerate () #14 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #15 0x00007fff894740b6 in __NSArrayEnumerate () #16 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #17 0x00007fff894740b6 in __NSArrayEnumerate () #18 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #19 0x00007fff894740b6 in __NSArrayEnumerate () #20 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #21 0x00007fff894740b6 in __NSArrayEnumerate () #22 0x00007fff8a1b2960 in -[NSView(NSInternal) _updateTrackingAreas] () #23 0x00007fff8a1b237c in _handleInvalidCursorRectsNote () #24 0x00007fff8a6ac851 in __35-[NSWindow _postInvalidCursorRects]_block_invoke_02794 () #25 0x00007fff894420c7 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ () #26 0x00007fff89442031 in __CFRunLoopDoObservers () #27 0x00007fff8941d4a8 in __CFRunLoopRun () #28 0x00007fff8941cdd2 in CFRunLoopRunSpecific () #29 0x00007fff89a72774 in RunCurrentEventLoopInMode () #30 0x00007fff89a72454 in ReceiveNextEventCommon () #31 0x00007fff89a723a3 in BlockUntilNextEventMatchingListInMode () #32 0x00007fff8a0d7fa3 in _DPSNextEvent () #33 0x00007fff8a0d7862 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] () #34 0x00007fff8a0cec03 in -[NSApplication run] () #35 0x00007fff8a073656 in NSApplicationMain () #36 0x00000001000013a2 in main #37 0x0000000100001374 in start ()
解决方法
目前尚不清楚这里存在问题.当视图几何体发生变化或者只要感觉需要重新计算跟踪区域时,appTrait会多次调用updateTrackingAreas方法.例如,在动画的情况下,当边界随时间快速变化时,您的方法将在每个runloop中快速连续调用.
仅供参考,改变任何视图的状态可能不是一个好主意,或者除了在该方法中添加或删除跟踪区域之外还有其他任何操作.在这里,您将更改按钮的alpha状态.这可能最好放在其他地方.