即使应用程序处于空闲状态,NSOutlineView也会不断更新

时间:2018-03-14 21:05:53

标签: objective-c macos cocoa nstableview nsoutlineview

我的macOS应用程序处于空闲状态,但NSOutlineView不断更新并占用40%的CPU。我调用的唯一代码是objectValueForTableColumn NSOutlineViewDataSource方法,大约每秒20次。

使用Instruments看起来主要的runloop不断寻找要提交的Core Animation任务。 (见下文46-44)。

  59 libdyld.dylib 3435.0  start
  58 FrogRadio 3435.0  main /Users/robertdodson/Pro/dev/FrogRadio/FrogRadio/FrogRadio/Main/main.m:13
  57 AppKit 3435.0  NSApplicationMain
  56 AppKit 3435.0  -[NSApplication run]
  55 AppKit 3426.0  -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]
  54 AppKit 3409.0  _DPSNextEvent
  53 HIToolbox 3408.0  _BlockUntilNextEventMatchingListInModeWithFilter
  52 HIToolbox 3408.0  ReceiveNextEventCommon
  51 HIToolbox 3401.0  RunCurrentEventLoopInMode
  50 CoreFoundation 3393.0  CFRunLoopRunSpecific
  49 CoreFoundation 3386.0  __CFRunLoopRun
  48 CoreFoundation 3192.0  __CFRunLoopDoObservers
  47 CoreFoundation 3185.0  __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
  46 AppKit 3158.0  __65+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayRefresh]_block_invoke
  45 QuartzCore 3117.0  CA::Transaction::commit()
  44 QuartzCore 2957.0  CA::Transaction::run_commit_handlers(CATransactionPhase)
  43 AppKit 2957.0  __37+[NSDisplayCycle currentDisplayCycle]_block_invoke
  42 AppKit 2948.0  ___NSWindowGetDisplayCycleObserver_block_invoke.5902
  41 AppKit 2936.0  -[NSWindow displayIfNeeded]
  40 AppKit 2935.0  -[NSView displayIfNeeded]
  39 AppKit 2874.0  -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
  38 AppKit 2872.0  -[NSView _oldDisplayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]
  37 AppKit 2816.0  -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]
...

我的应用中没有核心动画代码。我最近重构了,这是一个新问题,但我看不出我做了什么导致它。

这里有什么想法吗?

谢谢, 罗布

更新:在objectValueForTableColumn调用时添加完整堆栈跟踪:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x000000010001a3db FrogRadio`-[FRGTree outlineView:objectValueForTableColumn:byItem:](self=0x0000600000002b10, _cmd="outlineView:objectValueForTableColumn:byItem:", outlineView=0x0000000101c04130, tableColumn=0x000060c000082300, item=0x00006000000e7600) at FRGTree.m:101
frame #1: 0x00007fff2cd52756 AppKit`-[NSTableView preparedCellAtColumn:row:] + 471
frame #2: 0x00007fff2cdd60af AppKit`-[NSOutlineView preparedCellAtColumn:row:] + 51
frame #3: 0x00007fff2cd523e7 AppKit`-[NSTableView _drawContentsAtRow:column:withCellFrame:] + 50
frame #4: 0x00007fff2cdd601f AppKit`-[NSOutlineView _drawContentsAtRow:column:withCellFrame:] + 92
frame #5: 0x00007fff2cd520f2 AppKit`-[NSTableView drawRow:clipRect:] + 2186
frame #6: 0x00007fff2cd51568 AppKit`-[NSTableView drawRowIndexes:clipRect:] + 527
frame #7: 0x00007fff2cdd0ec2 AppKit`-[NSOutlineView drawRowIndexes:clipRect:] + 112
frame #8: 0x00007fff2cc6fced AppKit`-[NSTableView drawRect:] + 1522
frame #9: 0x00007fff2d3bac21 AppKit`_NSViewDrawRect + 83
frame #10: 0x00007fff2cc53b38 AppKit`-[NSView _drawRect:clip:] + 1819
frame #11: 0x00007fff2cc9bf62 AppKit`-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 1735
frame #12: 0x00007fff2cc9c42f AppKit`-[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] + 2964
frame #13: 0x00007fff2cc51a52 AppKit`-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 938
frame #14: 0x00007fff2cc522c1 AppKit`-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 3097
frame #15: 0x00007fff2cc522c1 AppKit`-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 3097
frame #16: 0x00007fff2cc522c1 AppKit`-[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 3097
frame #17: 0x00007fff2cc511db AppKit`-[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] + 327
frame #18: 0x00007fff2d3bc1d8 AppKit`-[NSView _oldDisplayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 2051
frame #19: 0x00007fff2cc50261 AppKit`-[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 253
frame #20: 0x00007fff2cc4c4b8 AppKit`-[NSView displayIfNeeded] + 1581
frame #21: 0x00007fff2cc4be56 AppKit`-[NSWindow displayIfNeeded] + 321
frame #22: 0x00007fff2d3ec2d9 AppKit`___NSWindowGetDisplayCycleObserver_block_invoke.5902 + 308
frame #23: 0x00007fff2cc4b962 AppKit`__37+[NSDisplayCycle currentDisplayCycle]_block_invoke + 695
frame #24: 0x00007fff3a65878f QuartzCore`CA::Transaction::run_commit_handlers(CATransactionPhase) + 49
frame #25: 0x00007fff3a657301 QuartzCore`CA::Transaction::commit() + 171
frame #26: 0x00007fff2d403658 AppKit`__65+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayRefresh]_block_invoke + 283
frame #27: 0x00007fff2f548127 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
frame #28: 0x00007fff2f54804f CoreFoundation`__CFRunLoopDoObservers + 527
frame #29: 0x00007fff2f52a6a8 CoreFoundation`__CFRunLoopRun + 1240
frame #30: 0x00007fff2f529f43 CoreFoundation`CFRunLoopRunSpecific + 483
frame #31: 0x00007fff2e841e26 HIToolbox`RunCurrentEventLoopInMode + 286
frame #32: 0x00007fff2e841b96 HIToolbox`ReceiveNextEventCommon + 613
frame #33: 0x00007fff2e841914 HIToolbox`_BlockUntilNextEventMatchingListInModeWithFilter + 64
frame #34: 0x00007fff2cb0cf5f AppKit`_DPSNextEvent + 2085
frame #35: 0x00007fff2d2a2b4c AppKit`-[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044
frame #36: 0x00007fff2cb01d6d AppKit`-[NSApplication run] + 764
frame #37: 0x00007fff2cad0f1a AppKit`NSApplicationMain + 804
frame #38: 0x00000001000456e2 FrogRadio`main(argc=3, argv=0x00007ffeefbff340) at main.m:13
frame #39: 0x00007fff56e41115 libdyld.dylib`start + 1

更新2:我的NSOutlineViewDataSource代码:

- (NSInteger) outlineView:(NSOutlineView *)outlineView     numberOfChildrenOfItem:(id)item
{
     return (item == nil) ? 1 : ((FRGTreeNode*)item).children.count;
}

- (BOOL) outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
    return [((FRGTreeNode*)item) isExpandable];
}

- (id) outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
    return (!item) ? _rootNode : ((FRGTreeNode*)item).children[index];
}

- (id) outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
    NSLog(@"tree: %@",((FRGTreeNode*)item).nodename);
    return ((FRGTreeNode*)item).nodename;
}

一些注意事项:NSLog方法每秒都会多次调用。此外,即使发生这种情况,outlineView也能正常工作。

1 个答案:

答案 0 :(得分:1)

我在每个单元格的outlineView dataCellForTableColumn中调用setNeedsDisplay,以便更新突出显示是正确的,这是一个坏主意。我会使这段代码变得更聪明。