9

非常に速くスクロールするときに発生する傾向があるios 7を使用して、UICollectionView内で奇妙なクラッシュが発生します。同様の問題が Apple Developer Forms で報告されています: https://devforums.apple.com/message/901009#901009

誰かがこれを経験し、修正/回避策を見つけたのではないかと思いますか?

フロー レイアウトで構成された基本的な UICollection ビューを使用しています。ネットワーク経由でjsonデータから入力されています。データは定期的に変更されます。それが行われると、reloadDataメソッドが呼び出されます。ネットワーク コールバックの 1 つがバックグラウンド スレッドでコールバックしているのではないかと心配していたので、reload メソッドが常にメイン スレッドで呼び出されることを確認しました。これは間違いなくそうではありません。

NSZmobies をオンにすると、クラッシュが発生したときに次のログ メッセージが表示されます。

*** -[NSIndexPath section]: message sent to deallocated instance 0x218b74c0

また、Zombies トレース テンプレートを使用して Instruments にアタッチされたアプリを実行したところ、クラッシュにつながる一連の呼び出しの詳細を示す次のスタック トレースを取得できました。

すべての呼び出しは iOS フレームワーク レベルの呼び出しであり、アプリケーションの呼び出しではないことに注意してください。

   0 libsystem_malloc.dylib malloc_zone_calloc
   1 libsystem_malloc.dylib calloc
   2 libobjc.A.dylib class_createInstance
   3 libobjc.A.dylib +[NSObject allocWithZone:]
   4 Foundation +[NSIndexPath indexPathWithIndexes:length:]
   5 UIKit +[NSIndexPath(UITableView) indexPathForRow:inSection:]
   6 UIKit -[UICollectionViewFlowLayout _layoutAttributesForItemsInRect:]
   7 UIKit -[UICollectionViewFlowLayout layoutAttributesForElementsInRect:]
   8 UIKit __45-[UICollectionViewData validateLayoutInRect:]_block_invoke
   9 UIKit -[UICollectionViewData validateLayoutInRect:]
  10 UIKit -[UICollectionView layoutSubviews]
  11 UIKit -[UIView(CALayerDelegate) layoutSublayersOfLayer:]
  12 QuartzCore -[CALayer layoutSublayers]
  13 QuartzCore CA::Layer::layout_if_needed(CA::Transaction*)
  14 QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*)
  15 QuartzCore CA::Context::commit_transaction(CA::Transaction*)
  16 QuartzCore CA::Transaction::commit()
  17 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*)
  18 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
  19 CoreFoundation __CFRunLoopDoObservers
  20 CoreFoundation CFRunLoopRunSpecific
  21 CoreFoundation CFRunLoopRunInMode
  22 GraphicsServices GSEventRunModal
  23 UIKit UIApplicationMain
  24 Mixlr main /Users/saman/Desktop/mixlr-iphone/Mixlr/main.m:14
  25 libdyld.dylib start
4

1 に答える 1

7

ユーザーがアクティブにスクロールしている場合、コレクションはアクティブにセルとヘッダーを要求しています。したがって、これが発生している間に、バッキング データ セットを変更して reloadData を呼び出しましたが、データが変更されたが reloadData がまだ発行されていないウィンドウがあります。

正しい場合、解決策は、ユーザーがアクティブにスクロールしていないときにのみ適用される変更セットを作成することです。

また、reloadData を使用することは、小さな爪に大きなハンマーを使用することです。可能であれば、個々のセルとビューを挿入、削除、または更新します。

編集: この状況は、人々がUITableViewsで経験していることと非常によく似ています。reloadData はすぐに返されることに注意してください - CollectionView はリロードをキューに入れ、現在の実行ループ サイクルの最後に実行するようにスケジュールします (これがどのように行われるかはわかりませんが、dispatch_async NSLogs を送信することで、実際に実行されることを確認できます)。

私のコレクションビューに表示されているのは、アクティブなスクロール中に、セルが作成されるとメインスレッドメッセージが表示され、次にリロードデータが呼び出され、次に表示可能なセルの現在のセットに対する didDisplay デリゲートメッセージが表示され、次に reloadData が返されることです。新しいセットを要求し始めます (クラッシュするかどうかを確認するために、はるかに小さくしました)。

現時点で私ができる最善のアドバイスは、データ モデルの変更をラップしてから reloadData メッセージをディスパッチ ブロックにラップし、すべてを同時に送信することです (または、すべてを 1 つのメソッドで実行します。

于 2013-10-18T12:31:35.947 に答える