2017-06-01 33 views
0

在我的应用我有下面的代码段:编写等效代码为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方法是在同一个类中定义的,它是一个实例方法。

但是,这似乎不工作,这意味着我得到一个不好的内存访问崩溃。

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

编辑:下面 感谢@dgatwood解释代码修复该问题

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

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

你的'pingWithBlock:'方法在哪里?并定义“不起作用”。 – rmaddy

+0

刚刚更新了我的问题 –

+0

不要编辑你的问题的答案。发布实际的答案。 – rmaddy

回答

0

这是一种奇怪的。 NSTimer保留其目标。也许这不会发生在这种情况下,因为__weak,但我认为它无论如何。 *耸耸肩*

无论哪种方式,这听起来像一个多线程竞争条件:

  • 您的计时器没有保留的对象,因此它可能消失在任何时间。
  • 别的东西保留对象。
  • 计时器计划在构造计时器时正在运行的线程的runloop中。
  • 在别的线程中引用另一个对象的引用。
  • 计时器在第一个线程中触发,并且归零弱引用未归零,因为该对象仍处于摧毁自身的中途。
  • 发生崩溃。

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

+0

谢谢你,阅读槽你的解释给我带来了正确的实施! –

+0

“也许这不会因为__weak而发生在这种情况下”这是无关紧要的。弱和强是本函数中局部变量的语义。它与如何通过论证无关。只有*值*被传递 - 它与变量或所有权语义无关。 – newacct

+0

我相信也是这种情况,这就是为什么行为没有意义,除非编译器中存在ARC错误,因为NSTimer根据文档保留其对象。 Self被自称的当前方法强制保留(否则该代码不会运行),并且定时器增加了保留计数,这意味着它应该由定时器保留,即使在其他任何保留它停止执行之后所以,在这个过程的任何时候,保留数不可能降到0,除非我错过了一些非常微妙的东西。 – dgatwood