I got a problem with the NSTimer
and the userInfo
.
In the docs Apple writes that the system keeps a strong reference to the Timer (and therefore the userInfo?) though sometimes when I'm trying to access parts of the userInfo object I'm getting a Bad Access exception. (Afaik that means something really bad happened)
Without further ado, here's how my object looks like that I pass to the userInfo:
@interface MyObject
@property (nonatomic, assign) u_int8_t cmd;
@property (nonatomic, assign) NSNumber *_id;
@end
And here's how I set the Timer:
NSTimer *myTimer = [NSTimer timerWithTimeInterval:10 target:self selector:@selector(someMethod:) userInfo:message repeats:NO];
[[NSRunLoop mainRunLoop] myTimer forMode:NSDefaultRunLoopMode];
The method that gets triggered when the Timer fires
-(void) someMethod:(NSTimer *)timer{
MyObject* mObject = [timer userInfo];
u_int8_t cmd = mObject.cmd; // This works
NSNumber *_id = mObject._id; // Bad access
}
Note: The userInfo itself isn't nil. Neither is the u_int8_t
nil or whatsoever. But as soon as I try to access the NSNumber
object I'm receiving the following exception (not necessarily every time):
Crashed: com.apple.main-thread
EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x00000000
What happens if I add a strong
property to the NSNumber object? Would this fix the issue and why? Why does this problem happen in the first place?
As NSNumber
is an object you need to use the strong
attribute, which is the default, so change the @property
declaration to:
@property (nonatomic) NSNumber *_id;
And using _id
as the identifier is a bad idea as id
is an Objective-C keyword, and you will likely confuse yourself at some point.