4

私のプロジェクトには、NSButtonNSView(他のビューのコンテナー)を備えたウィンドウがあります。ボタンをクリックすると、コンテナのサブビューが次のように変更されます。

[containerView replaceSubview:displayedSubview with:nextView];

containerViewに追加された最初のサブビューには、 NSTableCellViewサブクラスのオブジェクトで満たされた(バインディングを使用した)ビューベースのTableViewがあります。

このサブクラス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 ()
4

1 に答える 1

3

ここに問題があるかどうかは明確ではありません。updateTrackingAreas メソッドは、ビューのジオメトリが変更されたとき、またはトラッキング エリアを再計算する必要があると感じたときに、AppKit によって複数回呼び出されることを意図しています。たとえば、時間の経過とともに境界が急速に変化するアニメーションの場合、メソッドは実行ループごとに立て続けに呼び出されます。

参考までに、ビューの状態を変更したり、そのメソッドで追跡領域を追加または削除する以外のことを実際に行ったりすることは、おそらく良い考えではありません。ここでは、ボタンのアルファ状態を変更しています。それはおそらく別の場所に配置するのが最適です。

于 2012-11-24T19:11:03.947 に答える