应用程序在从加载集合视图导航时崩溃
场景: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)。因此,设置和读取它的代码不会发生冲突(列举的崩溃)
以上是 应用程序在从加载集合视图导航时崩溃 的全部内容, 来源链接: utcz.com/qa/260206.html