I have a custom TabbarViewController that basically hides the standard tab view. I attached a button that, when pressed, will animate a menu to the screen. Everything works fine while using the application for long time, but at some point it will crash with a EXC_BAD_ACCESS or a SIGABRT.
Curious thing is when i added a NSLog for printing tabbarController and menuView just before checking if menuView is a subview of tabbarController, it crashed on the NSLog line (to me looks like one of them is released but there is no explicit call and they both are retained).
This crash never happened on the simulator. Any ideas on what’s wrong?
AppDelegate.h
UIButton *ribbon;
RibbonMenu* menu;
@property (nonatomic, retain) CustomTabbarController* tabbarController;
@property (nonatomic, retain) UIView* menuView;
AppDelegate.m
@synthesize tabbarController;
@synthesize menuView;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
tabbarController = [[CustomTabbarController alloc] init];
[tabbarController setTabBarHidden:YES animated:NO];
tabbarController.viewControllers = [NSArray arrayWithObjects: EventsNavigation, StyleNavigation, BrandNavigation, MemberNavigation, settingsNavigation, nil];
ribbon = [UIButton buttonWithType:UIButtonTypeCustom];
[ribbon retain];
UIImage* img = [UIImage imageNamed:@"toppart.png"];
[ribbon setImage:img forState:UIControlStateNormal];
ribbon.frame = CGRectMake(234,0,86,97);
//MENU SELECTOR
[ribbon addTarget:self action:@selector(didClickMenu) forControlEvents:UIControlEventTouchUpInside];
[tabbarController.view addSubview:ribbon];
self.window.rootViewController = tabbarController;
[self.window makeKeyAndVisible];
}
- (void) didClickMenu {
if (!menuView) {
menu = [[RibbonMenu alloc] init];
menuView = menu.view;
menuView.backgroundColor = [UIColor clearColor];
[blinkTimer invalidate];
ribbon.selected = NO;
}
if ([tabbarController.view.subviews containsObject:menuView]) {
[self removeMenu];
} else {
menuView.frame = CGRectMake(235,-370,82,432);
//**CRASH HERE**
[tabbarController.view insertSubview:menuView belowSubview:ribbon];
[UIView transitionWithView:menuView
duration:0.2
options:UIViewAnimationOptionCurveLinear
animations:^ { menuView.frame = CGRectMake(235,0,82,432);}
completion:nil];
}
}
-(void) removeMenu {
[UIView transitionWithView:menuView
duration:0.2
options:UIViewAnimationOptionCurveLinear
animations:^ { menuView.frame = CGRectMake(235,-370,82,432);}
completion:^(BOOL finished) {[menuView removeFromSuperview];}];
}
This is the crash log
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread: 0
Last Exception Backtrace:
0 CoreFoundation 0x35a5388f __exceptionPreprocess + 163
1 libobjc.A.dylib 0x33677259 objc_exception_throw + 33
2 CoreFoundation 0x35a53789 +[NSException raise:format:] + 1
3 CoreFoundation 0x35a537ab +[NSException raise:format:] + 35
4 UIKit 0x33313cf1 __windowForView + 157
5 UIKit 0x33155ccd -[UIView(Hierarchy) _postMovedFromSuperview:] + 21
6 UIKit 0x3315680d -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1169
7 UIKit 0x33172071 -[UIView(Hierarchy) insertSubview:belowSubview:] + 29
8 MyAppName 0x000c6af3 -[AppDelegate didClickMenu] (AppDelegate.m:247)
When you are assigning the value to
menuView, you are not using property but yo are using iVar ofmenuView.To use the property, you should assign the value to menuView by using self.
By accessing property, it will retain it. By accessing iVar, it will not retain it. So there are chances that, once you remove the
menuViewfrom itssuperView, it will get removed.