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

UITableViewCell中NSNotificationCenter观察者方法未触发问题求助

为什么stopActivityIndicator没有被NSNotification触发?

结合你贴的代码,我梳理了几个最可能导致这个问题的原因,以及对应的解决思路:


1. 观察者注册时机晚于通知发送

你是在plusButtonClicked:方法内部才给当前cell注册观察者,但如果showCorrectBannerAfterPlusButtonClicked:(也就是发送通知的方法)在观察者完成注册之前就执行了,那这个cell根本就没来得及监听通知,自然收不到。

举个例子:点击plus按钮后,你可能先触发了某个异步请求,请求完成的回调里直接发送了通知,但这时候cell的观察者还没注册完成——这种顺序颠倒的情况很容易出现。

修复方案:
把观察者注册的代码移到cell的初始化生命周期方法里,比如awakeFromNib或者initWithStyle:reuseIdentifier:,确保cell一创建就完成监听注册:

- (void)awakeFromNib {
    [super awakeFromNib];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopActivityIndicator) name:@"stopActivityIndicator" object:nil];
}

2. UITableViewCell复用导致的实例丢失

UITableView的cell是复用机制,如果触发通知的时候,原来的那个cell已经被滚出屏幕、被系统回收或者复用给了其他行,那原来的cell实例已经不是当前存在的实例了,通知自然无法传递到它。

而且你只在按钮点击时注册观察者,复用后的新cell如果没触发plusButtonClicked:,就不会注册观察者,也收不到通知。

修复方案:

  • 方案一:在cell的prepareForReuse方法里处理观察者(先移除旧监听再重新注册,避免重复注册),同时在dealloc里统一清理:
- (void)prepareForReuse {
    [super prepareForReuse];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"stopActivityIndicator" object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(stopActivityIndicator) name:@"stopActivityIndicator" object:nil];
    // 顺便重置UI状态
    self.plusButton.hidden = NO;
    [self.plusButtonActivityIndicator stopAnimating];
}

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
  • 方案二:放弃通知,改用更直接的回调方式。比如在cell里定义一个block回调,点击plus按钮时调用block通知ViewController,操作完成后,ViewController通过tableView拿到对应的cell实例,直接调用stopActivityIndicator方法:
// ExploreTableViewCell.h
@property (nonatomic, copy) void (^plusButtonClickedBlock)(ExploreTableViewCell *cell);

// ExploreTableViewCell.m
- (IBAction)plusButtonClicked:(id)sender {
    self.plusButton.hidden = YES;
    [self.plusButtonActivityIndicator startAnimating];
    if (self.plusButtonClickedBlock) {
        self.plusButtonClickedBlock(self);
    }
}

// ExploreViewController.m
// 在cellForRowAtIndexPath里设置block
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ExploreTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellID" forIndexPath:indexPath];
    __weak typeof(self) weakSelf = self;
    cell.plusButtonClickedBlock = ^(ExploreTableViewCell *clickedCell) {
        // 这里执行你的业务逻辑,比如请求
        // 请求完成后直接调用cell的方法
        [clickedCell stopActivityIndicator];
        // 或者如果是异步回调,比如:
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [clickedCell stopActivityIndicator];
        });
    };
    return cell;
}

3. 线程不匹配(可能性较低,但值得排查)

如果通知是在子线程发送的,而你的stopActivityIndicator里有UI操作,虽然这不会导致方法不调用,但可能会引发UI异常。不过也有可能因为线程问题导致通知传递异常,你可以确保通知在主线程发送:

-(void)showCorrectBannerAfterPlusButtonClicked:(NSNotification *)notification {
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:@"stopActivityIndicator" object:nil];
    });
}

内容的提问来源于stack exchange,提问作者JeeGee

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:55:54