简体   繁体   English

iOS 7中的UICollectionView奇怪崩溃

[英]UICollectionView strange crash in iOS 7

Im getting a strange crash inside UICollectionView using ios 7 which tends to be happening when scrolling very fast. 我在使用ios 7的UICollectionView中遇到了一个奇怪的崩溃,这种情况在滚动非常快时往往会发生。 A similar issue has been reported on the Apple Developer Forms here: https://devforums.apple.com/message/901009#901009 此处有关Apple Developer Forms的类似问题: https//devforums.apple.com/message/901009#901009

I'm wondering if anyone out there has experienced this and found a fix/workaround? 我想知道是否有人经历过这个并找到了修复/解决方法?

I'm using a basic UICollection view configured with flow layout. 我正在使用配置了流布局的基本UICollection视图。 It's being populated from json data over the network. 它是通过网络从json数据填充的。 The data periodically changes. 数据会定期更改。 When it does the reloadData method is called. 当它调用reloadData方法时。 I have checked to make sure the reload method is always called on the main thread, as I was worried that one of my network callbacks was calling back on a background thread. 我已经检查过以确保在主线程上总是调用reload方法,因为我担心我的一个网络回调是在后台线程上回调。 This is definitely not the case. 绝对不是这样的。

When turning on NSZmobies I get the following log message when the crash occurs: 打开NSZmobies时,崩溃发生时会收到以下日志消息:

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

I also ran my app attached to the Instruments using the Zombies trace template and was able to attain the following stack trace detailing the sequence of calls leading to the crash. 我还使用Zombies跟踪模板运行我的应用程序附加到仪器,并能够获得以下堆栈跟踪详细说明导致崩溃的调用序列。

Note all the calls are iOS framework level calls and not my application calls. 请注意, 所有调用都是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

If the user is actively scrolling, the collection is actively requesting cells and headers. 如果用户正在主动滚动,则该集合正在主动请求单元格和标题。 So while this is happening, you have modified the backing data set and called reloadData, but there is a window where the data has been changed but reloadData not yet issued. 因此,在发生这种情况时,您已修改了后备数据集并调用了reloadData,但是有一个窗口,其中数据已更改但尚未发出reloadData。

If correct, then the solution is to create a change set that only gets applied when the user is not actively scrolling. 如果正确,则解决方案是创建仅在用户未主动滚动时才应用的更改集。

Also using reloadData is using a big hammer on a small nail - if possible insert, delete, or update individual cells and views. 另外使用reloadData在小钉子上使用大锤子 - 如果可能的话插入,删除或更新单个单元格和视图。

EDIT: this situation is quite similar to what people are experiencing with UITableViews . 编辑:这种情况与人们使用UITableViews时遇到的情况非常相似。 Note that reloadData returns immediately - the CollectionView just queues the reload and schedules it to run at the end of the current runloop cycle (not sure how they do this, but by sending dispatch_async NSLogs you can verify it does in fact to it). 请注意,reloadData会立即返回 - CollectionView只是将重新加载队列并将其调度为在当前runloop循环结束时运行(不确定它们是如何执行此操作的,但是通过发送dispatch_async NSLog,您可以验证它实际上对它进行了验证)。

What I'm seeing in my collection view is that during active scrolling I'm getting main thread messages as cells are created, then the reload data call, then didDisplay delegate messages for the current set of viewable cells, then reloadData returns, then it starts asking for the new set (which I made much smaller to see if I could get your crash). 我在集合视图中看到的是,在活动滚动期间,我在创建单元格时获取主线程消息,然后重新加载数据调用,然后didDisplay委托当前可查看单元格集的消息,然后reloadData返回,然后它开始要求新的设置(我做得更小,看看我是否可以得到你的崩溃)。

I guess the best advice I can give you at this time is to wrap the data model changes then a reloadData message up in a dispatch block, and send all at the same time (or do all in a single method. 我想我现在能给你的最佳建议是将数据模型更改包装在一个调度块中,然后在一个调度块中将reloadData消息包起来,并在同一时间发送所有内容(或者在一个方法中完成所有操作)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM