1

我从应用程序中的服务器获取具有 secondsToEnd 值的信息,并在收到此信息后启动计数器。

我的项目包含一个滚动视图,因此为了避免由于滚动而锁定我的计时器,我通过以下方式将计时器添加到 NSRunLoop:

[[NSRunLoop currentRunLoop] addTimer:timer
                             forMode:NSRunLoopCommonModes];

我创建了一个名为的 NSTimer 属性,它是多么原始,计时器,这是我的 startTimer 函数的整个片段:

- (void)startTimer
{
    if (_timer || [_timer isValid]) [_timer invalidate], _timer = nil, [_timer release];

    NSTimer * timer = [[NSTimer alloc] initWithFireDate:[NSDate date]
                                               interval:1.0
                                                 target:self
                                               selector:@selector(timer:)
                                               userInfo:nil
                                                repeats:YES];

    [[NSRunLoop currentRunLoop] addTimer:timer
                                 forMode:NSRunLoopCommonModes];

    [self setTimer:timer];
    [timer release];
}

在 start 方法中检查无效的原因是因为 secondsToEnd 值达到 0 后,我收到一个新的,我再次调用 startTimer。

在我的 dealloc 方法中,我有这个:

if (_timer || [_timer isValid]) [_timer invalidate], _timer = nil, [_timer release];

但它不会失效吗?我究竟做错了什么?

4

2 回答 2

3

这些逗号分隔的语句以什么顺序执行?如果在调用 invalidate 或调用 release 时 _timer 为 nil 会发生什么?

if (_timer || [_timer isValid]) [_timer invalidate], _timer = nil, [_timer release];

试试这个,不需要检查 _timer 是否已经为零。如果它是 nil,那么方法调用什么也不做。

if ([_timer isValid]) {
    [_timer invalidate];
}
[_timer release];

在dealloc方法中不需要设置_timer = nil,这个方法结束后它的存储就没有了。

于 2011-09-20T11:45:51.290 回答
1

你应该先打电话[timer release],然后再打电话timer = nil。在 dealloc 方法中相同。如果外部对象在 autrelease 池中,则可能不会立即调用 dealloc 方法。在这些情况下,当系统决定最终删除您的对象时会调用它。所以它可能需要一些时间(如果你设置了断点)。

顺便说一句,我建议避免使用逗号语法,而是使用大括号内的块。它更容易阅读。

于 2011-09-20T11:32:30.737 回答