1

TabbarViewController基本的に標準のタブビューを非表示にするカスタムがあります。押すとメニューが画面にアニメーション化されるボタンを付けました。アプリケーションを長時間使用している間はすべて正常に動作しますが、ある時点でEXC_BAD_ACCESSまたはSIGABRT.

NSLog興味深いのは、印刷用にtabbarControllerを追加し、menuViewmenuView が のサブビューであるかどうかを確認する直前にtabbarController、行でクラッシュしたNSLogことです (そのうちの 1 つが解放されているように見えますが、明示的な呼び出しはなく、両方が保持されます)。

このクラッシュは、シミュレーターでは発生しませんでした。何が間違っているかについてのアイデアはありますか?

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

このクラッシュは、シミュレーターでも発生するはずです。あなたはdidClickMenumenuViewにアクセスしようとしています。ただし、見た目から、menuView という名前のインスタンス変数はありません。menuViewというプロパティがありますが、 を使用してこのプロパティを呼び出す必要がありますself.menuView

または、Xcode 4.4 以降を使用していて、プロパティを合成しない場合は、コンパイラがインスタンス変数を作成します。このインスタンス変数は、プロパティと同じ名前ですが、接頭辞 _ が付いています。この場合は_menuView.

于 2013-01-14T05:06:18.693 に答える
1

その鍵はコーディングスタイルにあると私は考えています。

リボンとメニューはグローバルですか? メニューを所有しているかどうかにかかわらず、代わりに、self.menuView を使用して保持するのではなく、menu.view を 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 に答える