检查NSTimer isValid时是否崩溃?

时间:2015-06-26 04:15:36

标签: ios sdk nstimer

我在控制台中收到此异常:

  

错误:

     

2015-06-25 23:12:01.841 Mac版复制[9512:584232]    - [_ NSViewLayoutAux invalidate]:无法识别的选择器发送到实例0x6000001657c0

检查我的计时器是否有效/何时使其无效。

if ([_staticTimer isValid]) {
    [_staticTimer invalidate];
    _selectionTimer = 
            [NSTimer scheduledTimerWithTimeInterval:2 target:self 
            selector:@selector(hideHUD) userInfo:nil repeats:NO];
}

if ([_selectionTimer isValid]) {
    [_selectionTimer invalidate];
    _selectionTimer = 
           [NSTimer scheduledTimerWithTimeInterval:2 target:self 
           selector:@selector(hideHUD) userInfo:nil repeats:NO];
}

这是我的新代码:

 if (_selectionTimer != nil) {
        [_selectionTimer invalidate];
        _selectionTimer = nil;
        _selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
    }

    if (_staticTimer != nil) {
        [_staticTimer invalidate];
        _staticTimer = nil;
        _selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
    }


@property  (strong )NSTimer *staticTimer;
    @property  (strong )NSTimer *selectionTimer;

我在使用zombie对象进行调试时出现此错误。

  

2015-06-26 00:39:45.523 Mac版复制[11191:824502] ***    - [CFRunLoopTimer release]:发送到解除分配的实例0x608000175e40的消息

3 个答案:

答案 0 :(得分:1)

这里有几个潜在的问题。

if (_staticTimer != nil) {
    [_staticTimer invalidate];
    _staticTimer = nil;
    _selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
}

你在这里做的是覆盖selectionTimer,即使它仍然可能包含仍在运行循环中安排的计时器。因此,如果您在此处重置该属性,则还应确保在执行此操作之前调用[_selectionTimer invalidate]

根据您在计时器触发时的操作,这可以解释CFRunLoopTimer上的崩溃。

在使用NSTimer时,对我来说非常有帮助的一般性建议:我建议将包含计划计时器的所有属性声明为weak,因为它们由运行循环保留无论如何。这样,您无需在使其失效后将其明确设置为nil,而是每次想要摆脱它时只需调用invalidate,它也会自动成为nil {1}}一旦它被运行循环触发,释放它可能保留的所有数据。 请注意,如果您要取消定时器或更换定时器之前仍需要调用invalidate,但在执行此操作后您不再需要将其设置为nil

答案 1 :(得分:0)

使其无效后,您应将NSTimer对象设置为nilinvalidate方法也会执行release。 如果你不这样做,就像isValid那样调用一个方法可能会导致你的崩溃。

if (_selectionTimer != nil) {
    [_selectionTimer invalidate];
    _selectionTimer = nil;
    // do something
}

点击这里

if (_staticTimer != nil) {
        [_staticTimer invalidate];
        _staticTimer = nil;
        //_selectionTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
        _staticTimer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(hideHUD) userInfo:nil repeats:NO];
    }

答案 2 :(得分:0)

来自文档:

  

因为运行循环维护计时器,从角度来看   内存管理通常不需要保持对a的引用   计划完毕后的计时器。由于计时器作为一个传递   当您将其方法指定为选择器时,您可以使参数无效   在该方法中适当的重复计时器。在很多   但是,您还需要选择使...无效   计时器 - 甚至可能在它开始之前。在这种情况下,您需要保持   对计时器的引用,以便您可以向其发送无效   适当时留言。如果您创建一个未安排的计时器(请参阅   “非计划的计时器”),那么你必须保持强烈的参考   计时器(在引用计数环境中,你保留它)这样   在使用之前不会解除分配。

所以你应该让计时器弱而不是强