3

古い iPhone プロジェクトを ARC を使用するように変換しています。モーダル ビュー コントローラーを提示していますが、それを閉じると EXC_BAD_ACCESS が発生します。理由がわかりません。また、ARC のしくみに関する基本的なことが欠けていると思われます。

提示されているView ControllerはCorrectionsControllerであり、デリゲートを使用して、提示しているView Controllerにそれを閉じるように知らせます。これらは、ヘッダー ファイルからの関連ビットです。

@protocol CorrectionsControllerDelegate
   - dismissCorrectionsController;
@end

@property (nonatomic, weak) id<CorrectionsControllerDelegate> correctionsDelegate;

コントローラーは次のメソッドで初期化されます。

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<CorrectionsControllerDelegate>)_delegate {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        self.correctionsDelegate = _delegate;   
        // do other init stuff
    }
    return self;
}

非表示ボタンは次のメソッドを呼び出します。

- (void)cancelCorrection {
    if (self.correctionsDelegate)
        [self.correctionsDelegate dismissCorrectionsController];  
        // EXC_BAD_ACCESS happens here
}

表示側のビュー コントローラーは、次のように CorrectionsController を初期化します。

// in .h file
@property (nonatomic, strong)    CorrectionsController *corrections;
@property (nonatomic, strong)   UINavigationController *secondNavigationController;

// in .m file
    NSString *nibName = @"CorrectionsController";
    self.corrections = [[CorrectionsController alloc] initWithNibName:nibName bundle:nil delegate:self];
    self.secondNavigationController = [[UINavigationController alloc] initWithRootViewController:self.corrections];
    if (isiPad()) {
        self.secondNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
    }
    [self presentViewController:self.secondNavigationController animated:YES completion:nil];

また、CorrectionsControllerDelegate プロトコルを実装します。

- (void)dismissCorrectionsController {
    [self dismissViewControllerAnimated:TRUE completion:nil];
}

さて、楽しい部分です。コードをステップ実行すると、実行は cancelCorrection に流れ、デリゲートに DismissCorrectionsController に入り、cancelCorrection に戻り、cancelCorrection の最後で EXC_BAD_ACCESS になります。

ここに画像の説明を入力

ここに画像の説明を入力

self.correctionsDelegate は常に有効なオブジェクトを指しているように見えます ([変数] ビューで調べると、期待するオブジェクトと値が表示され、コンソールで次のように表示されますが、問題ないようです)。

(lldb) po self.correctionsDelegate
<SyncController: 0x17b9a970>

私を本当に混乱させる部分:

1) スタック トレースは、 EXC_BAD_ACCESS が objc_retain 内で発生していることを示しています。 なんで? ここに保持されているものは何ですか?

2) 0x44 メモリ アドレスは何を参照していますか?

4

2 に答える 2

0

これまでに見つけた最良の説明は、モーダル コントローラー (CorrectionsController) は、dismissCorrectionsController ですぐに解放されたように見え、実行が cancelCorrection に戻ると無効になるということです。この変更により、クラッシュが修正されたようです:

- (void)cancelCorrection {
    [self.correctionsDelegate performSelector:@selector(dismissCorrectionsController) ];
}

この回答を承認済みとしてマークしますが、それでも私には完全に意味がありません。そのため、誰かが何が起こっているかについてより良い説明を持っている場合は、代わりにその回答を喜んで受け入れます。

于 2013-10-29T19:51:18.403 に答える
-1

この回答は、質問者alex_cを助けるには非常に遅いと思いますが、誰かを助けることができます。

コードに問題があります。

@protocol CorrectionsControllerDelegate
   - dismissCorrectionsController;
@end

ミスリターンタイプ。

@protocol CorrectionsControllerDelegate
   - (void)dismissCorrectionsController;
@end
于 2016-08-25T06:39:39.500 に答える