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

NSTimer的selector回调中如何获取关联的Car类对象引用

NSTimer绑定自定义对象方案解答

你的子类化方案不可行

原因有两点:

  1. NSTimer属于类簇类型,苹果官方明确不建议子类化。类簇的底层实现隐藏了大量内部逻辑,强行子类化很容易出现不可预期的运行异常。
  2. 你给出的示例代码存在本质错误:[NSTimer scheduledTimerWithTimeInterval...]返回的仍然是原生NSTimer实例,强制转换为CustomTimer类型访问car属性时,会直接触发找不到方法的崩溃。

更合理的实现方案

  • 方案1:使用NSTimer自带的userInfo参数传递Car对象
    这是官方设计的标准传参方式,实现成本最低。
    创建定时器时把Car对象传入userInfo:
// 遍历所有Car对象创建定时器
for (Car *car in self.carList) {
    [NSTimer scheduledTimerWithTimeInterval:car.triggerInterval target:self selector:@selector(timerTick:) userInfo:car repeats:YES];
}

回调中直接读取userInfo即可:

- (void)timerTick:(NSTimer *)timer
{
    Car *currentCar = timer.userInfo;
    NSLog(@"当前触发定时器的车辆名称:%@", currentCar.name);
    // 其他业务逻辑
}
  • 方案2:使用Block版本的定时器接口(iOS 10+支持)
    可以直接在Block中捕获对应的Car对象,不需要单独实现回调方法,代码更简洁,注意避免循环引用即可:
for (Car *car in self.carList) {
    __weak typeof(self) weakSelf = self;
    [NSTimer scheduledTimerWithTimeInterval:car.triggerInterval repeats:YES block:^(NSTimer * _Nonnull timer) {
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return;
        NSLog(@"当前触发定时器的车辆名称:%@", car.name);
        // 其他业务逻辑
    }];
}
  • 方案3:维护映射字典(特殊场景使用)
    如果需要同时传递多个自定义参数,也可以维护一个全局的NSMutableDictionary,用定时器的唯一标识作为key,存储对应的Car对象,回调时查询字典即可。不过该方案需要额外处理字典的线程安全和内存清理,复杂度更高,一般不推荐。

额外注意事项

  • 定时器不再使用时必须调用invalidate方法销毁,避免Target被循环引用无法释放。
  • 如果定时器需要在列表滑动时也正常触发,需要手动将定时器添加到NSRunLoop的NSRunLoopCommonModes模式中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 03:54:05