为 in iOS 9 编写等效代码

Write equivalent code for in iOS 9

在我的应用程序中有一段代码:

__weak __typeof(self)weakSelf = self;

_pingTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
                                             repeats:YES
                                               block:^(NSTimer * _Nonnull timer)

{
    __strong __typeof(weakSelf)strongSelf = weakSelf;
    [strongSelf pingWithBlock:nil];
}];

这在 iOS 10+ 中完美运行,但我需要该应用程序也支持 iOS 9。所以我需要提供一种对两者都适用的方法。

我试过这个:

__weak __typeof(self)weakSelf = self;

_pingTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
                                             target:weakSelf
                                           selector:@selector(pingWithBlock:)
                                           userInfo:nil
                                            repeats:YES];

pingWithBlock 方法在同一个 class 中定义,它是一个实例方法。

但这似乎不起作用,这意味着我遇到了严重的内存访问崩溃问题。

如果有人有任何建议,我们将不胜感激。

编辑: 感谢@dgatwood 的解释,下面的代码修复了这个问题

- (void)autoPing
{
   _pingTimer = [NSTimer scheduledTimerWithTimeInterval:self.autoCheckInterval
                                             target:self
                                           selector:@selector(pingWithBlock)
                                           userInfo:nil
                                            repeats:YES];
}

-(void)pingWithBlock
{
    [self pingWithBlock:nil];
}

这有点奇怪。 NSTimer 保留其目标。由于 __weak,在这种情况下可能不会发生这种情况,但我认为它确实发生了。 *耸肩*

不管怎样,这听起来像是一个多线程竞争条件:

  • 您的计时器未保留该对象,因此它可能随时消失。
  • 其他保留对象。
  • 计时器在构造计时器时 运行 线程的运行循环中调度。
  • 其他东西在另一个线程中处理对对象的引用。
  • 计时器在第一个线程中触发,归零弱引用尚未归零,因为对象仍在自我销毁的一半。
  • 发生崩溃。

最好的解决方法是让计时器保留目标对象(通过删除所有 weakSelf 内容)。如果计时器是重复计时器,请提供一种方法以允许处理封闭对象的代码取消该计时器,并注意始终调用它。