我有一个自定义TabbarViewController
,它基本上隐藏了标准的标签视图。我附上了一个按钮,当按下该按钮时,会将菜单设置为屏幕动画。在使用该应用程序很长一段时间内一切正常,但在某些时候它会因EXC_BAD_ACCESS
或SIGABRT
而崩溃。
奇怪的是,当我在检查menuView是NSLog
的子视图之前添加tabbarController
打印menuView
和tabbarController
时,它在{{1}上崩溃了line(对我来说看起来就像其中一个被释放但是没有明确的调用,它们都被保留了。)
这次崩溃从未在模拟器上发生过。关于什么是错的任何想法?
AppDelegate.h
NSLog
AppDelegate.m
UIButton *ribbon;
RibbonMenu* menu;
@property (nonatomic, retain) CustomTabbarController* tabbarController;
@property (nonatomic, retain) UIView* menuView;
这是崩溃日志
@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];}];
}
答案 0 :(得分:2)
此崩溃也应该在模拟器上发生。在didClickMenu
中,您尝试访问menuView。但是,从它看起来,你没有一个名为menuView的实例变量。您有一个名为menuView的属性,但您需要使用self.menuView
调用此属性。
或者,如果您使用的是Xcode 4.4或更高版本并且您没有合成属性,编译器将为您创建一个实例变量。此实例变量与属性具有相同的名称,但带有_前缀 - 在这种情况下,它将是_menuView
。
答案 1 :(得分:1)
我认为关键是编码风格。
功能区和菜单是否全球化?是否,你没有自己的菜单,而只是将menu.view分配给menuView,而不是使用self.menuView来保留。是的,我知道代码只是分配菜单而不释放它。
在Mac上运行的模拟器上很难发生,但在具有较少内存和较差能力的iPod touch上可能更容易。
众所周知,EXC_BAD_ACCESS是由于访问已发布的对象。 如果我是你,我会:
self.menuView = [[[RibbonMenu alloc] init] autorelease];
来拥有RibbonMenu的视图以供使用。答案 2 :(得分:1)
当您将值分配给menuView
时,您没有使用属性,但是您正在使用menuView
的iVar。
要使用该属性,您应该使用self将值赋值给menuView。
self.menuView = menu.view;
通过访问属性,它将保留它。通过访问iVar,它不会保留它。因此,一旦您从menuView
移除superView
,就有可能将其删除。
- (void) didClickMenu {
if (!menuView)
{
menu = [[RibbonMenu alloc] init];
**self.menuView = menu.view;**
menuView.backgroundColor = [UIColor clearColor];
[blinkTimer invalidate];
ribbon.selected = NO;
}
}