使用 NSTimer 传递原始参数的正确方法
我正在使用一个调用此方法的基本计时器:
- (void) refresh:(id)obj
{
if (obj == YES) doSomething;
}
我想从代码的某些区域以及计时器中调用此方法
[NSTimer scheduledTimerWithTimeInterval:refreshInterval
target:self
selector:@selector(refresh:)
userInfo:nil
repeats:YES];
当我将 YES
作为 userInfo< 的参数时/code> 参数,我收到
EXC_BAD_ACCESS
错误;这是为什么?
有人可以帮助我以正确的方式做到这一点,这样就不会有丑陋的选角之类的吗?
I'm using a basic timer that calls this method:
- (void) refresh:(id)obj
{
if (obj == YES) doSomething;
}
I want to call this method from certain areas of my code and also from a timer
[NSTimer scheduledTimerWithTimeInterval:refreshInterval
target:self
selector:@selector(refresh:)
userInfo:nil
repeats:YES];
When I put YES
as the argument for the userInfo
parameter, I get an EXC_BAD_ACCESS
error; why is this?
Can someone help me do this the right way so that there is no ugly casting and such?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
userInfo
参数必须是一个对象;它的类型是id
。YES
是一个原语,即值1
。为了确保userInfo
对象不会被释放,计时器会保留它。因此,当您传递YES
时,NSTimer 正在执行[(id)YES keep]
。在您自己的代码中尝试一下,看看会发生什么。 :-P作为 文档 规定,您为方法提供的选择器必须具有签名
这意味着您不能让 NSTimer 调用任何方法 -至少不是直接的。您可以使用上述签名创建一个特殊方法,该方法反过来会调用您想要的任何方法。
因此,假设您有一个名为
refresh:
的方法,并且您希望经常调用它,并传递YES
。你可以这样做:The
userInfo
parameter must be an object; it is typedid
.YES
is a primitive, namely the value1
. In order to make sure theuserInfo
object does not get deallocated, the timer retains it. So, when you passedYES
, NSTimer was doing[(id)YES retain]
. Try that in your own code and see what happens. :-PAs the Documentation states, the selector you give the method must have the signature
This means you can't have an NSTimer invoke just any method—not directly at least. You can make a special method with the above signature which in turn invokes any method you want though.
So, say you have a method called
refresh:
, and you want to call it every so often, passing itYES
. You can do this like so:在 Objective-C 中,原始类型不是对象。因此,您不能直接将其传递给需要 id(代表通用对象)的参数。您需要将其包装到
NSNumber
对象中。使用
并且
不要忘记在完成后使计时器无效并释放它。
顺便说一句,您不必将
BOOL
(或 C++bool
)与YES
或true
进行比较或其他什么。当您编写a>b
时,计算结果为 bool,而if
使用结果。你在那里所做的事情对我来说很奇怪。并不是说
if
之后的(..)
应该包含比较;而是应该包含比较。它应该包含一个布尔值。In Objective-C, a primitive type is not an object. So you can't directly pass it to an argument which expects an
id
, which stands for a generic object. You need to wrap it into anNSNumber
object.Use
and
Don't forget to invalidate and release the timer once it's done.
By the way, you don't have to compare a
BOOL
(or C++bool
) againstYES
ortrue
or whatever. When you writea>b
evaluates to a bool, andif
uses the result. What you're doing there is likewhich is quite strange to me. It's not that the
(..)
afterif
should contain a comparison; it should contain a bool.作为 kperryua 答案的后续,如果您想通过 userInfo 传递原语,您可以使用
NSNumber
或NSValue
将其装箱;对于布尔值,您需要使用 [NSNumber numberWithBool:YES],然后在计时器回调中调用boolValue
以获取原语。As a follow-up to kperryua's answer, if you want to pass a primitive through userInfo you can box it with
NSNumber
orNSValue
; in the case of a boolean, you'd want to use[NSNumber numberWithBool:YES]
, then callboolValue
in the timer callback to get back the primitive.