获取 NSGenericException 的原因:'*** Collection <NSConcreteHashTable: 0x282c34140> 在枚举时发生了变异。'
Posted
技术标签:
【中文标题】获取 NSGenericException 的原因:\'*** Collection <NSConcreteHashTable: 0x282c34140> 在枚举时发生了变异。\'【英文标题】:Getting NSGenericException with reason: '*** Collection <NSConcreteHashTable: 0x282c34140> was mutated while being enumerated.'获取 NSGenericException 的原因:'*** Collection <NSConcreteHashTable: 0x282c34140> 在枚举时发生了变异。' 【发布时间】:2020-01-21 07:29:55 【问题描述】:我得到这个 NSGenericException 的原因是 Collection <NSConcreteHashTable: 0x282c34140> was mutated while being enumerated
,即使我实际上并没有在我的代码中使用快速枚举。
当 NSFetchedResultsController 委托作为我的 Core Data 对象中的属性被调用时触发此崩溃,最终调用此方法:
- (void)mutateCoordinatesOf***ingAnnotations:(NSArray *)annotations
NSDictionary *coordinateValuesToAnnotations = [self groupAnnotationsByLocationValue:annotations]; // returns a dictionary with key: coordinate (saved as NSValue) -> NSMutableArray of MKAnnotation objects
for (int i=0; i<coordinateValuesToAnnotations.allKeys.count; i++)
NSValue *coordinateValue = coordinateValuesToAnnotations.allKeys[i];
NSMutableArray *outletsAtLocation = coordinateValuesToAnnotations[coordinateValue];
[self repositionAnnotations:outletsAtLocation];
- (void)repositionAnnotations:(NSMutableArray *)annotations
for (int i = 0; i < annotations.count; i++)
double heading = radiansBetweenAnnotations * i;
CLLocationCoordinate2D newCoordinate = [self calculateNewCoordinate];
id <MKAnnotation> annotation = annotations[i];
annotation.coordinate = newCoordinate; // this is where it crashes
基本上,我正在尝试更改 MKAnnotation 对象(实际上也是 CoreData NSManagedObject)的“坐标”值,但最终会崩溃。奇怪的是,我得到了 'collection was mutated while being enumerated' 错误,即使上面的代码中没有任何“快速枚举”。我的意思是,我正在更改可变数组中对象的一个属性,该数组本身就是字典的一部分。
不幸的是,由于“注释”是一个 NSManagedObject,我不能只是从数组中“复制”它,然后更改复制的值并替换数组中的对象。
崩溃报告如下所示:
*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <NSConcreteHashTable: 0x282c34140> was mutated while being enumerated.'
Last Exception Backtrace:
0 CoreFoundation 0x00000001c058696c __exceptionPreprocess + 224
1 libobjc.A.dylib 0x00000001c029f028 objc_exception_throw + 56
2 CoreFoundation 0x00000001c05862d4 __NSFastEnumerationMutationHandler + 120
3 libobjc.A.dylib 0x00000001c02b21a4 objc_enumerationMutation + 28
4 Foundation 0x00000001c08706a8 -[NSConcreteHashTable countByEnumeratingWithState:objects:count:] + 72
5 MapKit 0x00000001ce114b64 -[MKAnnotationManager observeValueForKeyPath:ofObject:change:context:] + 804
6 Foundation 0x00000001c093bf14 NSKeyValueNotifyObserver + 288
7 Foundation 0x00000001c093e01c NSKeyValueDidChange + 332
8 Foundation 0x00000001c093b740 NSKeyValueDidChangeWithPerThreadPendingNotifications + 148
9 CoreData 0x00000001c5006e38 _PF_ManagedObject_DidChangeValueForKey + 76
10 Foundation 0x00000001c093784c NSKVOForwardInvocation + 336
11 CoreFoundation 0x00000001c058adc0 ___forwarding___ + 676
12 CoreFoundation 0x00000001c058d3a0 _CF_forwarding_prep_0 + 92
13 CJournal 0x00000001049fc930 -[MapViewShared repositionAnnotations:] (MapViewShared.m:656)
14 CJournal 0x00000001049fc580 -[MapViewShared mutateCoordinatesOf***ingAnnotations:] (MapViewShared.m:616)
15 CJournal 0x0000000104a1fa98 -[MapViewController controllerDidChangeContent:] (MapViewController.m:1104)
16 CoreData 0x00000001c50572a4 __82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 5868
17 CoreData 0x00000001c5015aac developerSubmittedBlockToNSManagedObjectContextPerform + 160
18 CoreData 0x00000001c4ee01c4 -[NSManagedObjectContext performBlockAndWait:] + 208
19 CoreData 0x00000001c4ee981c -[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:] + 120
20 Foundation 0x00000001c095106c __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_2 + 24
21 CoreFoundation 0x00000001c04de99c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 24
22 CoreFoundation 0x00000001c04de9ec ___CFXRegistrationPost1_block_invoke + 64
23 CoreFoundation 0x00000001c04ddce4 _CFXRegistrationPost1 + 392
24 CoreFoundation 0x00000001c04dd97c ___CFXNotificationPost_block_invoke + 104
25 CoreFoundation 0x00000001c0456910 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1420
26 CoreFoundation 0x00000001c04dd2ac _CFXNotificationPost + 1264
27 Foundation 0x00000001c083fbfc -[NSNotificationCenter postNotificationName:object:userInfo:] + 60
28 CoreData 0x00000001c4eed264 -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 512
29 CoreData 0x00000001c4ee95fc -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1244
30 CoreData 0x00000001c4ee886c -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 980
31 CoreData 0x00000001c501b48c _performRunLoopAction + 376
32 CoreFoundation 0x00000001c0501524 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 32
33 CoreFoundation 0x00000001c04fc1c4 __CFRunLoopDoObservers + 416
34 CoreFoundation 0x00000001c04fc774 __CFRunLoopRun + 1288
35 CoreFoundation 0x00000001c04fbf40 CFRunLoopRunSpecific + 476
36 GraphicsServices 0x00000001ca779534 GSEventRunModal + 104
37 UIKitCore 0x00000001c4674a60 UIApplicationMain + 1936
38 CJournal 0x00000001048d8c44 main (main.m:20)
39 libdyld.dylib 0x00000001c037ae18 start + 0
有人可以帮我找到这里的问题吗?我使用的是什么我看不到的“枚举”?还是有其他事情发生?
【问题讨论】:
您正在从不同的线程更改您的注释数组 更改是在主线程上完成的,这也是 NSFetchedResultsController 正在监听的。 我的意思是你一次从不同的函数中改变你的数组 我在同一条线上遇到了同样的崩溃,但底层架构完全不同(没有核心数据,没有获取结果控制器)。就我而言,问题是崩溃很难重现。您是否找到了解决方案? 【参考方案1】:看起来当您更改坐标时,MKAnnotationManager
观察到更改,然后通过枚举计算其哈希表,也许您已经在枚举注释。
在任何情况下,您都不应该将模型对象添加到视图中,这会破坏 MVC。控制器的工作是通过注释对象获取模型并将其格式化为视图。一种方法是从您的fetchedObjects
创建MKPointAnnotation
s(或创建一个MKPointAnnotation
子类并使用将其存储在弱属性中的模型对象对其进行初始化)并将其添加到地图中。在 FRC 的 didChangeObject
中,您可以从模型对象更新注释。地图的注释视图正在对注释的坐标进行 KVO,因此它会自动更新其在地图上的位置。在模型对象上创建一个类别(参见docs)来存储延迟加载的注释(使用objc_setAssociatedObject
)。
【讨论】:
以上是关于获取 NSGenericException 的原因:'*** Collection <NSConcreteHashTable: 0x282c34140> 在枚举时发生了变异。'的主要内容,如果未能解决你的问题,请参考以下文章
NSGenericException',原因:'无法在视图上安装约束
*** 由于未捕获的异常“NSGenericException”而终止应用程序,原因:“开始日期不能晚于结束日期!”
由于未捕获的异常“NSGenericException”而终止应用程序,原因:“*** Collection <CALayerArray: 0x66522e0> 在枚举时发生了突变
应用程序因 - 未捕获的异常“NSGenericException”而终止,
未捕获的异常 'NSGenericException: 应用程序提供了一个 UIAlertController 样式的 UIAlertControllerStyleActionSheet