1

我有一个TabbarViewController基本上隐藏标准选项卡视图的自定义。我附加了一个按钮,当按下该按钮时,会在屏幕上显示一个菜单。长时间使用该应用程序时一切正常,但在某些时候它会因 aEXC_BAD_ACCESS或 a而崩溃SIGABRT

奇怪的是,当我添加了一个NSLog用于打印tabbarController并且menuView就在检查 menuView 是否是 的子视图之前tabbarController,它在线上崩溃了NSLog(在我看来,其中一个已被释放,但没有显式调用,它们都被保留)。

这种崩溃从未在模拟器上发生过。关于有什么问题的任何想法?

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];}];
}

这是崩溃日志

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)
4

3 回答 3

2

这种崩溃也应该发生在模拟器上。在didClickMenu您尝试访问 menuView。但是,从外观上看,您没有名为 menuView 的实例变量。您有一个名为 menuView的属性self.menuView,但您需要使用.

或者,如果您使用的是 Xcode 4.4 或更高版本并且您没有合成您的属性,编译器将为您创建一个实例变量。此实例变量与属性同名,但带有 _ 前缀——在本例中为_menuView.

于 2013-01-14T05:06:18.693 回答
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 的视图以供使用。

仅供参考:http: //developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html

于 2013-01-18T08:43:38.330 回答
1

当您将值分配给 时menuView,您没有使用属性,而是使用 的 iVar menuView

要使用该属性,您应该使用 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;
    }
 }
于 2013-01-21T16:51:14.887 回答