为什么我在不修改源 array/set 的代码中得到 NSFastEnumerationMutationHandler?

Why am I getting NSFastEnumerationMutationHandler in code that doesn't modify source array/set?

在我最新的应用程序版本的崩溃日志中,我得到了一个 NSFastEnumerationMutationHandler,然后是我的代码的崩溃引用 HKAnchoredObjectQuery initWithType,但我并不是故意改变 NSMutableSet sources我正在快速枚举。

这是我的代码:

    for(HKSource* source in sources){
        NSPredicate *predicate = [HKQuery predicateForObjectsFromSources:[NSSet setWithObject:source]];
        HKAnchoredObjectQuery *newQuery = [[HKAnchoredObjectQuery alloc] initWithType:quantityType predicate:predicate anchor:anchor limit:HKObjectQueryNoLimit completionHandler:^(HKAnchoredObjectQuery *query, NSArray *results, NSUInteger newAnchor, NSError *error) {
            completion(results);
        }];

        [healthStore executeQuery:newQuery];
    }

关于我触发 NSFastEnumerationMutationHandler 的原因有什么建议吗?我没有明确接触 sources 也没有复制它...有没有办法 HealthKit 可以修改 source?即使是,我认为修改 source 不应该触发它,因为我没有直接接触 sources。任何故障排除建议或错误发现将不胜感激。

以下是崩溃日志中的确切文本:

Latest Exception Backtrace:
1. libobjc.A.dylib     objc_exception_throw
2. CoreFoundation      _NSFastEumerationMutationHandler
3. App name             0x1000d8000
4. App name             0x1000d8000
5. App name             0x1000d8000
6. HealthKit           _79-[HKAnchoredObjectQuery initWithType:predicate:anchor:limit:completionHandler:]_block_invoke     <---this must be referring to my code above, as it's the only call to initWithType inside a fast enumeration
7. HealthKit           _81-[HKAnchoredObjectQuery deliverSampleObjects:deletedObjects:withAnchor:forQuery:]_block_invoke_2     <-- this is an internal HealthKit call. deliverSampleObjects is not a publicly listed method of the interface.

我的 SIM 卡或我的 phone 都没有崩溃,所以这是我必须继续的唯一信息。

看起来这发生在名为

的方法中某处的块中
[HKAnchoredObjectQuery initWithType:predicate:anchor:limit:completionHandler:]

所以我的猜测是有问题的块是完成处理程序,并且完成处理程序被异步调用 - 而其他人正在遍历同一个数组并可能修改它。

不幸的是,这个错误不显示是谁造成了麻烦,只显示了谁在找麻烦。我会在您自己的回调上设置一个断点,检查它是否是从快速枚举中调用的,并尝试找出还有谁可能正在修改数据。祝你好运。

代码段中名为 completion() 的块调用的一些代码正在迭代另一个集合,并且在修改该数组时这样做。请记住,HKAnchoredObjectQuerycompletionHandler 在后台线程上运行,因此当 completionHandler 被调用时,您的代码可能正在对对象执行不安全的并发操作。