添加NSToolbar后awakeFromNib与表格行数方法调用顺序异常问题
问题分析与解决:添加NSToolbar后NSTableView数据源调用顺序异常
问题原因
添加NSToolbar后触发的UI布局时机变化,打破了你之前依赖的awakeFromNib调用顺序:
awakeFromNib的调用顺序并非绝对固定:它是nib中所有对象完成初始化和Outlet连接后,逐个触发的方法。nib结构的变化(比如新增Toolbar)会改变对象的加载和唤醒顺序。- NSToolbar在加载过程中会触发窗口的提前布局计算,而窗口布局更新会直接触发NSTableView向数据源请求行数(即
numberOfRowsInTableView:),此时AppDelegate的awakeFromNib还未执行,self.songs是空数组,返回0导致表格无数据。 - 调用次数不稳定是因为:部分场景下,
awakeFromNib执行完成后,数据变化会通过KVO通知间接触发表格重新加载,因此会第二次调用数据源方法;若未触发该通知,则只会调用一次。
解决方案
方案1:调整数据初始化时机(推荐)
将数据初始化代码从awakeFromNib移到更早且时机确定的方法中,比如AppDelegate的applicationWillFinishLaunching:或applicationDidFinishLaunching:,这两个方法会在UI组件开始请求数据前执行:
- (void)applicationWillFinishLaunching:(NSNotification *)notification { self.songs = [NSMutableArray array]; Song *aSong; aSong = [[Song alloc] init]; aSong.title = @"Gaeta's Lament"; aSong.duration = 289; [self.songsController addObject:aSong]; aSong = [[Song alloc] init]; aSong.title = @"The Signal"; aSong.duration = 309; [self.songsController addObject:aSong]; aSong = [[Song alloc] init]; aSong.title = @"Resurrection Hub"; aSong.duration = 221; [self.songsController addObject:aSong]; aSong = [[Song alloc] init]; aSong.title = @"The Cult of Baltar"; aSong.duration = 342; [self.songsController addObject:aSong]; NSLog(@"Data initialized"); }
方案2:手动触发表格刷新(若坚持使用awakeFromNib)
在awakeFromNib的末尾手动调用表格的reloadData方法,确保数据初始化完成后强制表格重新加载:
- (void)awakeFromNib { self.songs = [NSMutableArray array]; Song *aSong; aSong = [[Song alloc] init]; aSong.title = @"Gaeta's Lament"; aSong.duration = 289; [self.songsController addObject:aSong]; aSong = [[Song alloc] init]; aSong.title = @"The Signal"; aSong.duration = 309; [self.songsController addObject:aSong]; aSong = [[Song alloc] init]; aSong.title = @"Resurrection Hub"; aSong.duration = 221; [self.songsController addObject:aSong]; aSong = [[Song alloc] init]; aSong.title = @"The Cult of Baltar"; aSong.duration = 342; [self.songsController addObject:aSong]; NSLog(@"awakeFromNib is called"); // 手动刷新表格 [self.tableView reloadData]; }
额外注意点
你代码中同时使用了self.songs数组和songsController(NSArrayController),但表格数据源返回的是self.songs.count,这里存在逻辑不一致:如果通过数组控制器管理数据,建议直接将表格的内容绑定到数组控制器,而非手动实现数据源方法,这样KVO会自动触发表格更新,避免这类时序问题。
内容的提问来源于stack exchange,提问作者AsmCoder8088
相关产品推荐
相关产品推荐

