NSTableView 的委托在创建行时收到 awakeFromNib 消息

Posted

技术标签:

【中文标题】NSTableView 的委托在创建行时收到 awakeFromNib 消息【英文标题】:NSTableView's delegate receive awakeFromNib message when a row is created 【发布时间】:2012-08-06 15:40:31 【问题描述】:

在我的项目中有一个 xib 文件,其文件所有者设置为 NSViewController 的子类。这个 xib 文件有一个 NSView,里面有一个 View Based NSTableView。 NSViewController 子类实现协议 NSTableViewDelegate,并且在 IB 中,NSTableView 的委托连接到文件的所有者。当通过绑定创建视图时,viewController 的 awakeFromNib 方法会被此调用堆栈调用:

#0  0x000000010000584b in -[TheViewController awakeFromNib] 
#1  0x00007fff890f9bd8 in -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] ()
#2  0x00007fff893101d6 in -[NSNib _instantiateNibWithExternalNameTable:] ()
#3  0x00007fff89310c7a in -[NSNib instantiateNibWithExternalNameTable:] ()
#4  0x00007fff892bcac4 in -[NSTableRowData _unarchiveViewWithIdentifier:owner:] ()
#5  0x00007fff892be57b in -[NSTableView(NSTableViewViewBased) makeViewForTableColumn:row:] ()
#6  0x00007fff892be1b2 in -[NSTableRowData _addViewToRowView:atColumn:row:] ()
#7  0x00007fff892bde7f in -[NSTableRowData _addViewsToRowView:atRow:] ()
#8  0x00007fff892bc415 in -[NSTableRowData _addRowViewForVisibleRow:withPriorView:] ()
#9  0x00007fff892bc19a in -[NSTableRowData _addRowViewForVisibleRow:withPriorRowIndex:inDictionary:withRowAnimation:] ()
#10 0x00007fff892bb469 in -[NSTableRowData _unsafeUpdateVisibleRowEntries] ()
#11 0x00007fff892bb001 in -[NSTableRowData updateVisibleRowViews] ()
#12 0x00007fff892930fb in -[NSTableView viewWillDraw] ()
#13 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#14 0x00007fff884d50b6 in __NSArrayEnumerate ()
#15 0x00007fff8917092d in -[NSView viewWillDraw] ()
#16 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#17 0x00007fff884d50b6 in __NSArrayEnumerate ()
#18 0x00007fff8917092d in -[NSView viewWillDraw] ()
#19 0x00007fff891fb455 in -[NSScrollView viewWillDraw] ()
#20 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#21 0x00007fff884d50b6 in __NSArrayEnumerate ()
#22 0x00007fff8917092d in -[NSView viewWillDraw] ()
#23 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#24 0x00007fff884d50b6 in __NSArrayEnumerate ()
#25 0x00007fff8917092d in -[NSView viewWillDraw] ()
#26 0x00007fff89247e0d in -[NSBox viewWillDraw] ()
#27 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#28 0x00007fff884d50b6 in __NSArrayEnumerate ()
#29 0x00007fff8917092d in -[NSView viewWillDraw] ()
#30 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#31 0x00007fff884d50b6 in __NSArrayEnumerate ()
#32 0x00007fff8917092d in -[NSView viewWillDraw] ()
#33 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#34 0x00007fff884d50b6 in __NSArrayEnumerate ()
#35 0x00007fff8917092d in -[NSView viewWillDraw] ()
#36 0x00007fff89170bed in __22-[NSView viewWillDraw]_block_invoke_0 ()
#37 0x00007fff884d50b6 in __NSArrayEnumerate ()
#38 0x00007fff8917092d in -[NSView viewWillDraw] ()
#39 0x00007fff8916ff84 in -[NSView _sendViewWillDrawInRect:clipRootView:] ()
#40 0x00007fff8913c3f1 in -[NSView displayIfNeeded] ()
#41 0x00007fff891f93f8 in -[NSWindow _reallyDoOrderWindow:relativeTo:findKey:forCounter:force:isModal:] ()
#42 0x00007fff891f8a18 in -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] ()
#43 0x00007fff891f85ff in -[NSWindow orderWindow:relativeTo:] ()
#44 0x00007fff890f9c96 in -[NSIBObjectData nibInstantiateWithOwner:topLevelObjects:] ()
#45 0x00007fff890d8b7d in loadNib ()
#46 0x00007fff890d80a9 in +[NSBundle(NSNibLoading) _loadNibFile:nameTable:withZone:ownerBundle:] ()
#47 0x00007fff890d7ede in -[NSBundle(NSNibLoading) loadNibNamed:owner:topLevelObjects:] ()
#48 0x00007fff890d7cbe in +[NSBundle(NSNibLoading) loadNibNamed:owner:] ()
#49 0x00007fff890d447f in NSApplicationMain ()
#50 0x0000000100001432 in main

awakeFromNib 方法不应该只在 viewController 实例化后才调用?

【问题讨论】:

也看到了这个。真烦人。 【参考方案1】:

根据我的经验,任何 xib 文档File's Owner 似乎都会收到-awakeFromNib 消息每当从该 xib 文件加载新视图时。正如您所注意到的,当基于视图的表视图从 xib 文件创建新行时,就会发生这种情况。

我知道没有办法阻止这种情况的发生,除了可能要跟踪您调用awakeFromNib 的次数并仅在第一次执行初始化代码。

或者更好将您的初始化逻辑放在另一个具有更可靠时机的方法中 - 例如在-loadView 中,在调用super 之后。我会这样做:

- (void)loadView 
    [self vvViewWillLoad];
    [super loadView];
    [self vvViewDidLoad];


- (void)vvViewDidLoad 
    ... // initialization material here

【讨论】:

根据文档,这是真的:developer.apple.com/library/mac/documentation/Cocoa/Reference/…:

以上是关于NSTableView 的委托在创建行时收到 awakeFromNib 消息的主要内容,如果未能解决你的问题,请参考以下文章

取消选择 NSTableView 行时出现异常

NSTableView 委托不工作/不填充单元格

.reloadData() 没有调用 NSTableView 委托方法

NSTableView 绑定和 tableViewSelectionDidChange

使用没有 nib 的 NSTableView 创建 NSScrollView — TableView 上缺少约束

NSTableview 中选定行的标签颜色