モーダルビューコントローラーを表示すると iPhone がクラッシュする
-
05-07-2019 - |
質問
別のビューがモーダルで表示された直後にモーダル ビューを表示しようとしています (2 番目は表示される読み込みビューです)。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Show load
LoadViewController *loader = [[LoadViewController alloc] init];
[self presentModalViewController: loader animated:NO];
[loader release];
}
しかし、これを行うと、「プログラムが信号を受信しました:「EXC_BAD_ACCESS」。」エラーが発生しました。
スタック トレースは次のとおりです。
0 0x30b43234 in -[UIWindowController transitionViewDidComplete:fromView:toView:]
1 0x3095828e in -[UITransitionView notifyDidCompleteTransition:]
2 0x3091af0d in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:]
3 0x3091ad7c in -[UIViewAnimationState animationDidStop:finished:]
4 0x0051e331 in run_animation_callbacks
5 0x0051e109 in CA::timer_callback
6 0x302454a0 in CFRunLoopRunSpecific
7 0x30244628 in CFRunLoopRunInMode
8 0x32044c31 in GSEventRunModal
9 0x32044cf6 in GSEventRun
10 0x309021ee in UIApplicationMain
11 0x00002154 in main at main.m:14
何か案は?完全に困惑してます!読み込み中のビューは空なので、エラーの原因となるような処理は何も起こっていません。同じイベントループか何かで2つのビューをモーダルに起動することと関係がありますか?
ありがとう、
マイク
編集:非常に奇妙な...読み込みビューが少し遅れて表示されるように少し変更しましたが、これは正常に動作します。したがって、それは同じイベント ループ内の何かであるように見えます。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Show load
[self performSelector:@selector(doit) withObject:nil afterDelay:0.1];
}
- (void)doit {
[self presentModalViewController:loader animated:YES];
}
解決
わずかな遅延の後に読み込みビューが表示されるように少し変更しましたが、これは正常に機能します!そのため、同じイベントループ内にあるように見えます!
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// Show load
[self performSelector:@selector(doit) withObject:nil afterDelay:0.1];
}
- (void)doit {
[self presentModalViewController:loader animated:YES];
}
他のヒント
iOS 4で同じエラーを再現したと思います。私のアプリケーションでは、最初のモーダルビューを表示した直後に2番目のモーダルビューを表示しようとすると、一貫してクラッシュが発生しました。気が狂って数時間苦労しました。
このスレッドの投稿を読んだ後、Tab Bar Applicationテンプレートを使用して、簡単で再現可能な例を作成しようとしました。 「FirstViewController.m」のボタンクリックに応答した後、UIImagePickerControllerを使用して最初のモーダルビューを表示できました。 (imagePickerControllerDidCancelメッセージを処理した後)UIImagePickerControllerを再度表示しようとすると、アプリケーションは同じエラーでクラッシュしました。
デバイスでは、何が起こっているのか、まったく手がかりがありませんでした。ただし、シミュレータでコードを実行したとき、コンソールでこのメッセージを受け取ることができたのは幸運でした。
***キャッチされていない例外 'NSInternalInconsistencyException'によるアプリの終了、理由: '移行中にモーダル移行を開始しようとしています。 viewDidAppear / viewDidDisappearが現在の移行が完了したことを知るまで待ちます。
だから、エラーメッセージのアドバイスに従い、viewDidAppear(この特別なモードにいることを示すフラグを使用して)を待ってから、2番目のモーダルビューを読み込むのが私の唯一の選択肢のようです。
完全性のための完全なスタックトレースは次のとおりです。
** Call stack at first throw: ( 0 CoreFoundation 0x0238c919 __exceptionPreprocess + 185 1 libobjc.A.dylib 0x024da5de objc_exception_throw + 47 2 CoreFoundation 0x02345078 +[NSException raise:format:arguments:] + 136 3 Foundation 0x000ab8cf -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 116 4 UIKit 0x00544317 -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:] + 212 5 UIKit 0x0035c769 -[UIViewController presentModalViewController:withTransition:] + 2937 6 TestTempDelete 0x000021cf -[FirstViewController showImagePicker] + 167 7 Foundation 0x0002fcea __NSFireDelayedPerform + 441 8 CoreFoundation 0x0236dd43 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19 9 CoreFoundation 0x0236f384 __CFRunLoopDoTimer + 1364 10 CoreFoundation 0x022cbd09 __CFRunLoopRun + 1817 11 CoreFoundation 0x022cb280 CFRunLoopRunSpecific + 208 12 CoreFoundation 0x022cb1a1 CFRunLoopRunInMode + 97 13 GraphicsServices 0x02bf12c8 GSEventRunModal + 217 14 GraphicsServices 0x02bf138d GSEventRun + 115 15 UIKit 0x002beb58 UIApplicationMain + 1160 16 TestTempDelete 0x00001eb4 main + 102 17 TestTempDelete 0x00001e45 start + 53
これがお役に立てば幸いです。
**前述のように、isIgnoringInteractionEventsを使用します
//Check if the app is ignoring interatctions, if so, add a delay for 1 sec
if([[UIApplication sharedApplication] isIgnoringInteractionEvents]==TRUE) {
[currentViewController performSelector:@selector(presentModalViewController:animated:) withObject:screen afterDelay:1];
} else {
[currentViewController presentModalViewController:screen animated:YES];
}
Interface Builderでコードにリンクされたボタンをクリックした後にこれを取得した場合、1つのボタンにリンクされた2つのアクションを持っている可能性があります(ボタンにリンクされたモーダルビューがある場合、ボタンを複製し、別のモーダルビューをリンクしました)。これは両方をオフにしようとするため、そのメッセージで失敗します。
同じ例外に遭遇しました
キャッチされなかった例外「NSInternalInconsistencyException」によりアプリを終了します。理由:' トランジションがすでに進行中に、 から へ へのモーダルトランジションを開始しようとしています。現在の遷移が完了したことを確認するには、viewDidAppear/viewDidDisapear を待ちます。
前に提案したように、モーダル遷移の表示を遅らせようとしましたが、実際には役に立ちませんでした。その後、私は持っていることに気づきました 複数の IBAction がボタンの TouchUpInside イベントに接続されています。. 。私の場合、2 つの IBAction が開始されます。人物ピッカーをモーダルで表示し、画像ピッカーをモーダルで表示します。これはエラー メッセージの説明です。複数の IBAction が接続されているかどうかを確認してください。
問題は、viewDidAppearが含まれているメソッドを初期化して提示するメソッド、またはLoadViewControllerのinit / viewDidLoad / viewWillAppearメソッドにある可能性が最も高いです。
いくつかのブレークポイントを設定し、クラッシュするまでフォローします...
UIButton
をクリックしてモーダルビュー
を開くと、同様のエラーが発生しました。 UIButtonの
リスナーを UIControlEventAllEvents
から UIControlEventTouchUpInside
に変更しました。基本的に、 Touch Down Inside
でモーダルビューを起動し、次に Touch Up Inside
で再度起動しました。
名前の不一致が原因で同じ問題が発生しました
HelpViewController *controller = [[HelpViewController alloc] initWithNibName:@"HelpView" bundle:nil];
および実際の.xibファイルの名前。
この問題は、私が遭遇した問題と関係があると思います。 簡単に再現できます:
新しいXCodeプロジェクト"ユーティリティアプリケーション"を作成します。 FlipsideViewController.mで 次のメソッドを挿入するだけです:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear: animated];
[self showInfo];
}
これを行う場合、アプリケーションを起動すると、フリップサイドビューが有効になります 離れて。 [完了]を押すとすぐにフリップビューのボタン、戻る viewDidAppearを再度起動し、フリップサイドに戻るメインビューに移動します。 ビュー。フリップビューが表示されるとすぐに、アプリケーションが停止します-メモリがありません デアロケータが呼び出されます-それはちょうどホームボタンを押したようなものです。
これらのビューでいくつかの追加のプロパティを使用していたときに、例外も発生しました。 そのため、コードを最小限に抑えました...
私は本当に手がかりがありません、この問題が本当に何なのか...
よろしく、 トバイアス
これは、 viewDidAppear
のサポートルーチンが何をしているかに本当に依存します。たとえば、 presentModalViewController:animated:
が loader
を保持しない場合、 loader
がリリースされました(投稿したルーチンの最後)。
読み込みビューを実装するのと同じ手法を使用しているときに、同様の問題がありました。読み込みの最後に読み込みビューが閉じられるとクラッシュしました。 私の場合、ロードビューが閉じられるとすぐにviewDidAppearが再度呼び出され、ロードビューを再度表示しようとしたことが原因で問題が発生しました。 ロードビューが以前に表示されたかどうかを確認するだけで修正しました。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(needDisplayLoader)
[self presentModalViewController: loader animated:NO];
}
次に、Loaderビューを閉じる前にneedDisplayLoaderをNOに設定します
これが役立つことを願っています...
たった今この問題に遭遇し、上記のselector:afterDelayの提案を使用して修正しました。追加するだけで、iPhone OS 4.0ベータ版で(修正なしで)コンパイルし、クラッシュしません!そのため、XCodeのバグは次世代で修正されたようです。これは今日私たちの誰にとっても良いことではありませんが、皆さんが知っているように、それは本当にXemのバグであり、コーディングスタイルで間違ったことをしているわけではありません。
まったく同じ問題がありました。上記の提案で解決しました...
[self performSelector:@selector(doit)withObject:nil afterDelay:0.5];
0.5秒の遅延を使用する必要がありました。 UIPickerViewControllerモーダルの直後にpresentModalViewControllerを実行していた可能性があります。
この問題が発生したばかりで、プロトコルデリゲートの割り当てを解除したことが原因であることが判明しました。
ループの理由は、ロードする新しいView ControllerがデフォルトでviewDidAppearメソッドを持ち、それが持っているためだと思います
[super viewDidAppear animated];
これは、メインビューコントローラーのviewDidAppearに再度コールバックすることを意味します。ループに行くように
提示するViewcontrollerでは、スーパーviewdidapperなしで次のようなメソッドがあります:
-(void)viewDidAppear:(BOOL)animated{
//[super viewDidAppear:animated]; no super
}
EXC_BAD_ACCESS
はメモリエラーです。おそらくすでにリリース/割り当て解除されているオブジェクトを使用しようとしているのでしょう。この回答は、これらの問題をデバッグするためのヒントを提供します。