我正在使用调用此方法的基本计时器:
- (void) refresh:(id)obj
{
if (obj == YES) doSomething;
}
我想从我的代码的某些区域以及计时器
中调用此方法[NSTimer scheduledTimerWithTimeInterval:refreshInterval
target:self
selector:@selector(refresh:)
userInfo:nil
repeats:YES];
当我将YES
作为userInfo
参数的参数时,我收到EXC_BAD_ACCESS
错误;这是为什么?
有人可以帮助我以正确的方式做到这一点,这样就没有丑陋的演员吗?
答案 0 :(得分:10)
userInfo
参数必须是对象;它是键入的id
。 YES
是一个原语,即值1
。为了确保userInfo
对象不被取消分配,计时器会保留它。因此,当您通过YES
时,NSTimer正在执行[(id)YES retain]
。在您自己的代码中尝试,看看会发生什么。 :-P
作为Documentation状态,您为方法指定的选择器必须具有签名
- (void)timerFireMethod:(NSTimer*)theTimer
这意味着您不能让NSTimer只调用任何方法 - 至少不是直接调用。您可以使用上述签名创建一个特殊方法,然后调用您想要的任何方法。
所以,假设您有一个名为refresh:
的方法,并且您希望每隔一段时间调用它一次,并将其传递给YES
。你可以这样做:
// somewhere
{
[NSTimer scheduledTimerWithTimeInterval:refreshInterval
target:self
selector:@selector(invokeRefresh:)
userInfo:nil
repeats:YES];
}
- (void)invokeRefresh:(NSTimer *)timer {
[self refresh:YES];
}
- (void)refresh:(BOOL)flag {
if (flag) {
// do something
}
}
答案 1 :(得分:4)
在Objective-C中,基本类型不是对象。因此,您无法直接将其传递给期望id
的参数,该参数代表通用对象。您需要将其包装到NSNumber
对象中。
使用
NSTimer*timer=[NSTimer scheduledTimerWithTimeInterval:refreshInterval
target:self
selector:@selector(refresh:)
userInfo:[NSNumber numberWithBool:YES]
repeats:YES];
和
- (void) refresh:(NSTimer*)timer
{
NSNumber* shouldDoSomething=[timer userInfo];
if ([shouldDoSomething boolValue]) doSomething;
}
一旦完成,不要忘记使计时器无效并释放。
顺便说一句,您不必将BOOL
(或C ++ bool
)与YES
或true
或其他内容进行比较。当你写
if(a>b) { ... }
a>b
评估为bool,if
使用结果。你在那里做的就像
if((a>b)==YES) { ... }
这对我来说很奇怪。并不是(..)
之后的if
应该包含比较;它应该包含一个布尔。
答案 2 :(得分:0)
作为kperryua答案的后续内容,如果您想通过userInfo传递原语,可以使用NSNumber
或NSValue
将其打包;在布尔值的情况下,您需要使用[NSNumber numberWithBool:YES]
,然后在计时器回调中调用boolValue
以获取原语。