【问题标题】:Can't access NSTimer's userInfo无法访问 NSTimer 的 userInfo
【发布时间】:2014-01-22 09:58:16
【问题描述】:

我有这个代码。

- (void)scheduleTimerAfterDelay:(NSTimeInterval)delay {
    dispatch_async(dispatch_get_main_queue(), ^{
        _timer = [NSTimer scheduledTimerWithTimeInterval:delay
                                                  target:self
                                                selector:@selector(triggerTimer:)
                                                userInfo:[NSString stringWithFormat:@"%f", delay]
                                                 repeats:NO];
    });
}

- (void)triggerTimer:(NSTimer *)timer {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"Triggered timer after %@ s.", _timer.userInfo); // <-- Exception thrown!
        // Do stuff
    });
}

但是当定时器触发时,_timer.userInfo 会导致Exception: EXC_BAD_ACCESS (code=1, address=0xc))

我在这里错过了什么?在异常行的断点处打印_timer 表明_timer 是&lt;__NSCFTimer: 0x14ec8cb0&gt;。但我也无法通过 lldb 访问 userInfo。我正在使用 ARC。

【问题讨论】:

    标签: objective-c ios7 automatic-ref-counting nstimer


    【解决方案1】:

    userInfo 应该是字典:

    _timer = [NSTimer scheduledTimerWithTimeInterval:delay
                                              target:self
                                            selector:@selector(triggerTimer:)
                                            userInfo:@{ @"name" : @"Zinedine Zidane",
                                                        @"age"  : @42 }
                                             repeats:NO];
    

    你显然需要改变你在选择器中访问它的方式:

    在调用dispatch_async()之前需要保留userInfo

    - (void)triggerTimer:(NSTimer *)timer {
        NSString *s = timer.userInfo;    // Strong reference!
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Triggered timer after %@ s.", s);
            // Do stuff
        });
    }
    

    【讨论】:

    • 文档说明它应该是 id。 developer.apple.com/library/mac/documentation/cocoa/reference/… 即便如此,将其更改为字典并不会改变结果。
    • @MdaG 我已经更新了我的答案。您还需要将其作为字典访问。
    • 这里的问题是,Timer 在 mainThread 上触发了“triggerTimer”,而您再次要求在 maintherad 上调度。所以分派的工作将在下一个 runLoop 上完成。但是定时器对象只对这个 Runloop 有效。
    • 谢谢你这样做。 userInfo 不需要是字典,任何 NSObject 都可以。 NSString 在我的例子中。
    • 您的解决方案有效,因为您在调度之前保留了字典,不是,因为它是字典。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 2015-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多