• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

应用程序在从加载集合视图导航时崩溃

IOS 来源:Shinigami 4次浏览

场景:UINavigationViewController包含UICollectionViewControllers。每个集合视图都需要从JSON API获取数据,这可能需要一些时间。然后,集合视图中的每个单元向服务器发送自己的请求,从而获取缩略图。 (为了清楚起见,我创建了一个sequence diagram来展示我如何做这件事,不包括缩略图请求,我已禁用它进行调试)。应用程序在从加载集合视图导航时崩溃

这是代码的样子:

-(void)buildDisplayItems 
{ 
    NSLog(@"Collection VC (object: %@) with collection (object: %@) building display items on thread %@ (main thread: %c)", self, self.showingCollection, [NSThread currentThread], [NSThread isMainThread]); 
    [self.showingCollection buildDisplayItemsWithPhotoBatch:self.nextBatch++]; // <-- this waits for the server request to be made, come back and get processed into arrays before returning. 
    self.photos = self.showingCollection.photos; 
    self.collections = self.showingCollection.subcategories; 
    // Past this point, I cannot think of how these arrays would possibly get changed to trigger the 'mutated while being enumerated' errors. 
    [self.collectionView reloadData]; 
} 

的问题是,如果用户返回上在某一适当的时候在导航视图中,我得到了以下错误之一:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <NSConcreteMapTable: 0x1f047c80> was mutated while being enumerated.'

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSSetM: 0x203f26b0> was mutated while being enumerated.'

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[3]'

为了发生这些错误,我必须尝试3-4次选择某个项目,以便将其集合视图压入导航堆栈,然后快速按下后退按钮。显然,前两个错误给我的第一印象是数据源数组正在以某种方式被修改,但是我写的任何东西都是这样做的。然后,我想可能是因为cellForItemAtIndexPath返回后,每个单元格的缩略图都会被加载,所以我禁用了它,但没有任何改变。

我撒了一些NSLogs,发现这是在集合视图调用其委托方法时发生的。我一定要添加以下内容:

-(void)viewWillDisappear:(BOOL)animated 
{ 
    if (self.showingCollection != nil) { 
     [self.showingCollection cancelOperations]; //for network requests 
     NSLog(@"Collection VC (object: %@) will disappear", self); 
    } 
} 

-(void)dealloc 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
    self.collectionView.delegate = nil; 
    self.collectionView.dataSource = nil; 
    self.collectionView = nil; 
} 

但是这并没有帮助阻止错误。事实上,有些时候发生崩溃时,没有“Collection VC会消失”的日志消息。

另一个问题是这些错误发生,并且调试器在UIApplicationMain行的主函数中停止(这是’断所有异常’断点),所以我无法确定如何触发错误。我已经启用僵尸,但没有来自他们的日志消息。 (编辑:有时它实际上停在一个空的线程,说“错误:地址不包含指向对象文件中的一节”部分)

如何设置这些集合视图,以便快速按下后退按钮不会结束世界?

编辑 我怎样才能找出什么是枚举时正在改变的集合?

UPDATE 我发现这个SO线程谈论无法获取堆栈跟踪。每次我上面是一个例外,它会给我像

*** First throw call stack: 
(0x327453e7 0x3a440963 0x32744ec1 0x330f72c7 0x330f769b 0x330f825b 0x330fa0c7 0x330faefd 0x33103cab 0x3498c519 0x3498d5f1 0x3498d915 0x349920d9 0x34991fe3 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x3268bacd 0x34991f97 0x330fa997 0x3498bf3d 0x345c73dd 0x34303513 0x343030b5 0x34303fd9 0x343039c3 0x343037d5 0x3434a567 0x3a87febb 0x3a87fb93 0x3a898fb8 0x32fe5fc7 0x3305d24f 0x3a88d0e1 0x3a88cfa8) 
libc++abi.dylib: terminate called throwing an exception 

按照该线程的建议,我实现了我自己捕获的异常处理程序堆栈跟踪,并将其打印出以下堆栈跟踪:

0 CoreFoundation      0x327453ff <redacted> + 186 
1 libobjc.A.dylib      0x3a440963 objc_exception_throw + 30 
2 CoreFoundation      0x32744ec1 <redacted> + 0 
3 Foundation       0x330f72c7 <redacted> + 422 
4 Foundation       0x330f769b <redacted> + 298 
5 Foundation       0x330f825b <redacted> + 202 
6 Foundation       0x330fa0c7 <redacted> + 242 
7 Foundation       0x330faefd <redacted> + 500 
8 Foundation       0x33103cab <redacted> + 390 
9 UIKit        0x3498c519 <redacted> + 128 
10 UIKit        0x3498d5f1 <redacted> + 196 
11 UIKit        0x3498d915 <redacted> + 88 
12 UIKit        0x349920d9 <redacted> + 84 
13 UIKit        0x34991fe3 <redacted> + 182 
14 CoreFoundation      0x3268bacd CFArrayApplyFunction + 176 
15 UIKit        0x34991f97 <redacted> + 106 
16 CoreFoundation      0x3268bacd CFArrayApplyFunction + 176 
17 UIKit        0x34991f97 <redacted> + 106 
18 CoreFoundation      0x3268bacd CFArrayApplyFunction + 176 
19 UIKit        0x34991f97 <redacted> + 106 
20 CoreFoundation      0x3268bacd CFArrayApplyFunction + 176 
21 UIKit        0x34991f97 <redacted> + 106 
22 CoreFoundation      0x3268bacd CFArrayApplyFunction + 176 
23 UIKit        0x34991f97 <redacted> + 106 
24 CoreFoundation      0x3268bacd CFArrayApplyFunction + 176 
25 UIKit        0x34991f97 <redacted> + 106 
26 Foundation       0x330fa997 <redacted> + 166 
27 UIKit        0x3498bf3d <redacted> + 124 
28 UIKit        0x345c73dd <redacted> + 72 
29 QuartzCore       0x34303513 <redacted> + 214 
30 QuartzCore       0x343030b5 <redacted> + 460 
31 QuartzCore       0x34303fd9 <redacted> + 16 
32 QuartzCore       0x343039c3 <redacted> + 238 
33 QuartzCore       0x343037d5 <redacted> + 316 
34 QuartzCore       0x3434a567 <redacted> + 170 
35 libsystem_c.dylib     0x3a87febb _pthread_tsd_cleanup + 174 
36 libsystem_c.dylib     0x3a87fb93 <redacted> + 118 
37 libsystem_c.dylib     0x3a898fb8 pthread_exit + 27 
38 Foundation       0x32fe5fc7 <redacted> + 10 
39 Foundation       0x3305d24f <redacted> + 1002 
40 libsystem_c.dylib     0x3a88d0e1 <redacted> + 308 
41 libsystem_c.dylib     0x3a88cfa8 thread_start + 8 

===========解决方案如下:

1:当您从集合视图离开视图控制器时,您是否无法在集合视图中委托引用和数据源,以便不再查询?

这也发生在表视图上,对象仍然存在,但数据或源不。

2:我还建议在修改集合时使用@synchronized(self)。因此,设置和读取它的代码不会发生冲突(列举的崩溃)


版权声明:本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系管理员进行删除。
喜欢 (0)