iOS insertSubview:belowSubview:与SIGABRT崩溃

时间:2013-01-14 04:59:02

标签: iphone ios ipad

我有一个自定义TabbarViewController,它基本上隐藏了标准的标签视图。我附上了一个按钮,当按下该按钮时,会将菜单设置为屏幕动画。在使用该应用程序很长一段时间内一切正常,但在某些时候它会因EXC_BAD_ACCESSSIGABRT而崩溃。

奇怪的是,当我在检查menuView是NSLog的子视图之前添加tabbarController打印menuViewtabbarController时,它在{{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];}];
}

3 个答案:

答案 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是由于访问已发布的对象。 如果我是你,我会:

  1. 将Xcode更新为最新版本。
  2. 不要为属性编写任何@synthesize代码。 Xcode将@synthesize menuView = _menuView。
  3. 尽可能避免使用全局变量,而是使用OOP中的属性。所以,我会写self.menuView = [[[RibbonMenu alloc] init] autorelease];来拥有RibbonMenu的视图以供使用。
  4. 仅供参考:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html

答案 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;
    }
 }