I have this strange crash relating to ARC auto-inserting objc_retains in my code.
I have the following two classes:
@interface MenuItem : NSObject
@prope
The reason for the crash was because I was using the wrong performSelector
.
NSObject
defines multiple versions of performSelector
. The one I was invoking was:
- (id)performSelector:(SEL)aSelector;
However the method I was invoking took an id
parameter. Eg:
- (void)someMethod:(id)sender;
Now ARC being the nice safe memory management system that it is tries to ensure that parameters are properly retained during the execution of a method. So even though my someMethod:
was empty ARC was producing code that looked like this:
- (void)someMethod:(id)sender
{
objc_retain(sender);
objc_release(sender);
}
The problem with this however was that I was invoking performSelector:
and not supplying a value for the sender
parameter. So sender
was pointing at random junk on the stack. Therefore when objc_retain()
was invoked the app crashed.
If I change:
MenuItem *item = [[MenuItem alloc] initWithTarget:widget
action:@selector(someMethod:)
object:nil];
to
MenuItem *item = [[MenuItem alloc] initWithTarget:widget
action:@selector(someMethod)
object:nil];
and
- (void)someMethod:(id)sender;
to
- (void)someMethod;
Then the crash goes away.
Similarly I can also change
[self.target performSelector:self.action];
to
[self.target performSelector:self.action withObject:nil];
if I want to follow the 'standard' form of target-action methods that take a single parameter. The benefit of the second form of performSelector
is that if I'm invoking a method that doesn't take a parameter it will still work fine.