You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 11:03:27