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?
The userInfo parameter must be an object; it is typed id. YES is a primitive, namely the value 1. In order to make sure the userInfo object does not get deallocated, the timer retains it. So, when you passed YES, NSTimer was doing [(id)YES retain]. Try that in your own code and see what happens. :-P
As the Documentation states, the selector you give the method must have the signature
- (void)timerFireMethod:(NSTimer*)theTimer
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 it YES. You can do this like so:
// 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
}
}
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 an NSNumber object.
Use
NSTimer*timer=[NSTimer scheduledTimerWithTimeInterval:refreshInterval
target:self
selector:@selector(refresh:)
userInfo:[NSNumber numberWithBool:YES]
repeats:YES];
and
- (void) refresh:(NSTimer*)timer
{
NSNumber* shouldDoSomething=[timer userInfo];
if ([shouldDoSomething boolValue]) doSomething;
}
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) against YES or true or whatever. When you write
if(a>b) { ... }
a>b evaluates to a bool, and if uses the result. What you're doing there is like
if((a>b)==YES) { ... }
which is quite strange to me. It's not that the (..) after if should contain a comparison; it should contain a bool.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With