So, I’m puzzled by a really weird crash occurring in my app.
Background: I have a class CustomButton overriding UIButton. Briefly, the interface looks like:
@interface CustomButton : UIButton
@property (nonatomic, getter = isLoading) BOOL loading;
@end
Implementation:
@implementation CustomButton
@synthesize loading = loading_;
- (id)init {
if ((self = [UIButton buttonWithType:UIButtonTypeCustom])) {
[self setTitle:NSLocalizedString(@"My Button", nil) forState:UIControlStateNormal];
[[self titleLabel] setShadowColor:[UIColor blackColor]];
[[self titleLabel] setShadowOffset:CGSizeMake(0, -1)];
[self setContentEdgeInsets:UIEdgeInsetsMake(0, 77, 0, 30)];
UIImage *backgroundImage = [[UIImage imageNamed:@"back.png"] stretchableImageWithLeftCapWidth:77 topCapHeight:0];
UIImage *highlightedBackgroundImage = [[UIImage imageNamed:@"back_highlighted.png"] stretchableImageWithLeftCapWidth:77 topCapHeight:0];
[self setBackgroundImage:backgroundImage forState:UIControlStateNormal];
[self setBackgroundImage:highlightedBackgroundImage forState:UIControlStateHighlighted];
[self sizeToFit];
}
return self;
}
- (void)setLoading:(BOOL)loading {
if (loading_ != loading) {
// Do fancy things
}
}
@end
Problem: I’m trying to use the button in a class, so I have property and so on:
...
@property(nonatomic, strong) CustomButton *customButton;
...
@syntesize customButton = customButton_;
...
- (void)aMethod {
self.customButton.loading = YES;
}
...
The button, of course, is initialized.
Then, upon executing the statement self.bookButton.loading = YES, I get this error
2012-08-28 12:54:25.091 MyApp[9465:15803] -[UIAccessibilityBundle
setLoading:]: unrecognized selector sent to instance 0x8650cc0
2012-08-28 12:54:25.091 MyApp[9465:15803] *** Terminating app due
to uncaught exception 'NSInvalidArgumentException', reason:
'-[UIAccessibilityBundle setLoading:]: unrecognized selector sent to
instance 0x8650cc0'
*** First throw call stack: (0x1ead022 0x203ecd6 0x1eaecbd 0x1e13ed0 0x1e13cb2 0x26bf5 0x257ce 0xfa938f 0xfa96a4 0xfa99a7 0xfb8aea
0x11600be 0x11603c7 0x1160436 0xf10e49 0xf10f34 0xc5bcaac 0xe04b54
0x272e509 0x1de4803 0x1de3d84 0x1de3c9b 0x27887d8 0x278888a 0xee0626
0x14cce 0x27b5 0x1) terminate called throwing an exception
I honestly have no idea about what to look for. It’s either something really really stupid, or something really subdle.
I’ve been searching on google/stackoverflow already of course, but I didn’t manage to get an answer.
Usually that error occurs, as far as I know, when the object doesn’t “understand” the sent message, but this shouldn’t be the case. I don’t even get a warning from the compiler.
If you have even just an idea of what I could look for or you want more details, let me know, thanks.
EDIT: forgot to specify that I am using ARC.
UPDATE: In the answers below Phillip Mills said that it might have been a premature memory release issue. It’s a good point, but Instrument didn’t find any zombie. Moreover, I’ve put a log right before the crashy statement, where I try print information about the CustomButton object and few things related to a UIButton, like the title. Everything looks ok. The title is the one I’ve set, the frame is there and so on… so I believe the object (an actual UIButton) exists and it’s also the expected one. The only thing is the “loading” property that messes everything up.
SOLUTION: the init method was the source of the problem. Instead of initializing an instance of the subclass of the button, it was initializing an instance of UIButton. So, conequentely, no “loading” properties could be found. Substituting init with initWithFrame and using the standard procedure to override the initializer, everything works great.
Still a mistery, though, the reason why I got UIAccessibilityBundle as the origin of the error and not a UIButton.
Are you casting anything to
(CustomButton *)in your app? Double-check the casts – you might be incorrectly casting something that’s not aCustomButtonand storing the result in thecustomButtonproperty.