ユーザーがコンテンツを作成すると表示および非表示になるビューがいくつかあるiPhone SDKアプリケーションがあります。しばらくデバイスでアプリケーションを使用した後、次のクラッシュが発生します。
Program received signal: “EXC_BAD_ACCESS”.
(gdb) backtrace
#0 0x33369ebc in objc_msgSend ()
#1 0x320e5248 in -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded] ()
#2 0x338b4a14 in -[NSObject performSelector:withObject:] ()
#3 0x320e5098 in -[UIAnimator stopAnimation:] ()
#4 0x320e4b7c in -[UIAnimator(Static) _advance:] ()
#5 0x320e4a34 in LCDHeartbeatCallback ()
#6 0x34350e60 in HeartbeatVBLCallback ()
#7 0x332e91c0 in IOMobileFramebufferNotifyFunc ()
#8 0x316532f8 in ?? ()
#9 0x33866b50 in __CFMachPortPerform ()
#10 0x338ae52a in CFRunLoopRunSpecific ()
#11 0x338adc1e in CFRunLoopRunInMode ()
#12 0x3434e1c8 in GSEventRunModal ()
#13 0x32002c30 in -[UIApplication _run] ()
#14 0x32001230 in UIApplicationMain ()
#15 0x00002ff8 in main (argc=1, argv=0x2ffff550) at /Developer/svn/MyCompany/iPhone/MyApplication/Other Sources/main.m:14
トレースからわかるように、私のコードで言及されているのはmainの呼び出しだけです。
XcodeからBuild and Analyzeを実行し、ターミナルからプロジェクトでclangアナライザーを実行するように設定しましたが、どちらもコードの問題を検出できません。 iOS SDKの最新リリースバージョンを使用しています(まだ4.1をダウンロードしていませんが、使用しているのは4.1より前のリリースのものです)。
また、シミュレーターを使用してInstrumentsでアプリケーションを実行しましたが、アプリにメモリリークはありません。
NSZombieEnabled
変数を使用して何かが見つかるかどうかを確認しようとしていますが、問題は、アプリケーションがクラッシュする前にアプリケーションを30〜40分ほど使用する必要があることであり、NSZombieEnabled
は、問題を見つけるのに役立ちません。
私が見たクラッシュは、モーダルビューが親ビューコントローラーのデリゲートを呼び出すときに発生したようです。親ビューコントローラーは、モーダルビューコントローラーを閉じる前に、いくつかの処理を行います。クラッシュにはアニメーション表示とスクロール表示への参照がいくつかありますが、それらに問題を引き起こすために何ができるのかわかりません。誰かが探すべきことについて何か提案がありますか?
編集:NSZombieEnabled
フラグをアプリケーションに入れました。デバイスでは、コンソールに次のメッセージが表示されます。
2010-09-11 17:10:33.970 MyApplication[9321:207] ***
-[MyViewController respondsToSelector:]: message
sent to deallocated instance 0x7489480
私の知る限りでは、アプリケーションで使用されるデリゲートをすべてのクラスのdeallocsでnilに設定しているので、次にどこを見ればいいのか悩んでいます。
malloc_history
pid addressコマンドでこれを実行しましたが、プロセスが見つからなかったため、9321、9321:207、および207を試しました。また、MallocStackLogging
変数を使用しようとすると、プログラムはデバイス上で実行すると、malloc:
コンソールでスタックログディレクトリメッセージを作成できず、プログラムがクラッシュします。
ああ、ところで、デバイスで動作していないように見えるので、インストゥルメントでゾンビチェックを使用できません。また、シミュレータで同じクラッシュが発生することはありません。
スタックフレーム#1のUIScrollView
は、おそらくデリゲートにアニメーションの終了を通知する必要がありますが、デリゲートはその時点で消えています。 NSZombieEnabled
を設定すると、おそらくこれを確認できます。
デリゲートは保持されないため、これはCocoaおよびCocoa Touchの一般的なエラーです。コード内でUIScrollView
またはUITableView
のデリゲートを探し、その時間より前にリリースされる可能性があるものを見つけてください。
私はこの問題に自分で取り組みました。
私は問題を抱えていました:
問題は、スクロールビューデリゲートメッセージが新しく割り当てを解除されたオブジェクトで発生し、クラッシュログが無意味なオブジェクト参照を指しているため、少し混乱していたことです。
修正は、ビューコントローラーのdeallocメソッドの最初の行として、scrollviewデリゲートをnilに設定することでした。
これが誰かを助けることを願っています!
完全を期すために、同じスタックトレース(iOS 6)を追加しますが、同じ問題が発生する可能性がありますが、実装が少し異なり、問題を再現するための正確な手順が異なります。
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x71f05631
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.Apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x3919b5d0 objc_msgSend + 1
1 UIKit 0x33421830 -[UIScrollView(UIScrollViewInternal) _delegateScrollViewAnimationEnded] + 48
2 UIKit 0x334217ba -[UIScrollView(UIScrollViewInternal) _scrollViewAnimationEnded:finished:] + 130
3 UIKit 0x334216a4 -[UIAnimator stopAnimation:] + 460
これはiOS 6で発生しており、UIScrollViewDelegateメソッドを実装したときに発生し始めました。
" -(void)scrollViewDidEndDecelerating:(UITableView *)tableView"
and made a call to:
"[tableView scrollToRowAtIndexPath: indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];".
アニメーションが開始し、「戻る」ボタンを押したときに問題が発生し、アニメーションが完了する前にビューコントローラーがポップオフしました。
再生するときは、アニメーションが始まってから完了する前に、必ず「戻る」ボタンを押してください。何度か試してみました。プログラムでビューコントローラーをポップオフして問題を再現しようとしましたが、再現できませんでした。 「戻る」ボタンを使わなければなりませんでした。私は単にdeallocで[myTableView release]を呼び出していました。解決策は、これらのプロパティの両方をnilに設定するためにここで説明したとおりです。
self.myTableView.delegate = nil;
self.myTableView = nil;
最初は、デリゲートはweak/assignタイプである必要があります。しかし、この場合のイベントには、スクロールアニメーションによって引き起こされる非常に一般的な微妙な障害があります。 ScrollViewsにアニメーションコンテンツオフセットの変更を使用する場合は、そのdelegateをnilにdeallocメソッドに設定する必要があります。
そうでなければ、次のようになります
[YourViewController respondsToSelector:]: message sent to deallocated instance
非常に一般的な例:
1. _tableView is ivar of YourViewController
2. _tableView.delegate = self;
3. - (void)scrollViewDidScroll:(UIScrollView *)scrollView is implemented at YourViewController
4. at some point you call [_tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionBottom animated:YES];
or [_tableView setContentOffset:CGPoint animated:YES]
and try to close YourViewController
_tableViewはCoreAnimationによって保持されますが、YourViewControllerは割り当て解除されます!
私の推測では、scrollviewのデリゲートは割り当て解除されたオブジェクトに設定されています。 deallocメソッドで、子オブジェクトのすべてのデリゲートをnilに設定してみてください。
これは、更新コントローラーをサブビューとしてテーブルビューに挿入した場合に発生する可能性があります(私のヒントですが、それを行うことはありません)...
上記のすべては私の問題を解決しなかったので、もう一度コードを掘り下げました。キーボードとICollectionViewアニメーション(そう、チャットです)を実行して現在のコントローラーを閉じると、クラッシュが発生することを認識しました。
アニメーション完了ブロックでスクロールを作成しようとすると、アプリケーションがクラッシュします:)
切るだけですべてうまくいきます!
幸せなコーディングとデバッグ:)
存在しないindexPathを指定してscrollToRowAtIndexPathを呼び出すと、このような動作が見られます