同步解决了由于未捕获的异常"NSGenericException"而终止应用的问题,原因:"*** 集合<__NSCFSet:>在枚举时发生了变化



我相信我已经找到了解决错误的解决方案,但是不明白我是否只是通过减慢代码来避免使用解决方案的种族条件,或者我是否只是我真正解决问题。

我的问题是2部分
1(为什么将dispatch.main.async更改为dispatch.main.sync会使错误消失,因为我已经正确编码了,或者我暂时只解决了问题?

2(我需要将所有dispatch.main.async更改为dispatch.main.sync的其他两个电话?

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

在本报告中,第二个答案特别说,永远不要使用dispatch.main.sync,因为它会导致僵局。第一个答案显示,您可能要使用同步,但可能会导致死锁。

global((中的main.sync是什么意思?

苹果报告错误如下:

Thread 5 name:  Dispatch queue: com.apple.cloudkit.operation-7BCFBC195B4B17C3.callback
Thread 5 Crashed:
0   libsystem_kernel.dylib          0x00000001b4e120dc 0x1b4def000 + 143580
1   libsystem_pthread.dylib         0x00000001b4e8b094 0x1b4e89000 + 8340
2   libsystem_c.dylib               0x00000001b4d6af4c 0x1b4d10000 + 372556
3   libsystem_c.dylib               0x00000001b4d6aeb4 0x1b4d10000 + 372404
4   libc++abi.dylib                 0x00000001b4437788 0x1b4436000 + 6024
5   libc++abi.dylib                 0x00000001b4437934 0x1b4436000 + 6452
6   libobjc.A.dylib                 0x00000001b444ee00 0x1b4449000 + 24064
7   libc++abi.dylib                 0x00000001b4443838 0x1b4436000 + 55352
8   libc++abi.dylib                 0x00000001b44438c4 0x1b4436000 + 55492
9   libdispatch.dylib               0x00000001b4cb47e8 0x1b4c54000 + 395240
10  libdispatch.dylib               0x00000001b4c5d324 0x1b4c54000 + 37668
11  libdispatch.dylib               0x00000001b4c5de74 0x1b4c54000 + 40564
12  libdispatch.dylib               0x00000001b4c664ac 0x1b4c54000 + 74924
13  libsystem_pthread.dylib         0x00000001b4e95114 0x1b4e89000 + 49428
14  libsystem_pthread.dylib         0x00000001b4e97cd4 0x1b4e89000 + 60628

当我以Xcode运行代码时,我可以在Xcode中重现错误并获取以下堆栈跟踪。

2019-07-31 19:51:07.893799-0400 My Toy Chest[49278:1080065] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x600002a24180> was mutated while being enumerated.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00000001106d38db __exceptionPreprocess + 331
    1   libobjc.A.dylib                     0x000000010f6f4ac5 objc_exception_throw + 48
    2   CoreFoundation                      0x00000001106d07ac __NSFastEnumerationMutationHandler + 124
    3   CoreData                            0x0000000110048dd4 -[NSManagedObjectContext executeFetchRequest:error:] + 3332
    4   My Toy Chest                        0x0000000109248bc0 $s12My_Toy_Chest21ActionFigureSpecificsC03setdeF8CoreDataSbyF + 1472
    5   My Toy Chest                        0x000000010923a4b2 $s12My_Toy_Chest21ActionFigureSpecificsC03setdeF0yyF + 546
    6   My Toy Chest                        0x0000000109313c6b $s12My_Toy_Chest22SharedDataActionFigureC03getfg26SpecificsICloudForCompletefG5ArrayyyFySaySo8CKRecordCGSg_s5Error_pSgtcfU_ + 3051
    7   My Toy Chest                        0x000000010931409c $s12My_Toy_Chest22SharedDataActionFigureC03getfg26SpecificsICloudForCompletefG5ArrayyyFySaySo8CKRecordCGSg_s5Error_pSgtcfU_TA + 12
    8   My Toy Chest                        0x0000000109315233 $s12My_Toy_Chest22SharedDataActionFigureC013fetchCompletefG18SpecificsFromCloud10completionyySaySo8CKRecordCGSg_s5Error_pSgtc_tFySo13CKQueryCursorCSg_AKtcfU0_ + 1331
    9   My Toy Chest                        0x0000000109315e01 $s12My_Toy_Chest22SharedDataActionFigureC013fetchCompletefG18SpecificsFromCloud10completionyySaySo8CKRecordCGSg_s5Error_pSgtc_tFySo13CKQueryCursorCSg_AKtcfU0_TA + 49
    10  My Toy Chest                        0x00000001092373b4 $sSo13CKQueryCursorCSgs5Error_pSgIeggg_ACSo7NSErrorCSgIeyByy_TR + 132
    11  CloudKit                            0x000000010f51e84d -[CKQueryOperation _finishOnCallbackQueueWithError:] + 613
    12  CloudKit                            0x000000010f51795a -[CKOperation _finishInternalOnCallbackQueueWithError:] + 582
    13  CloudKit                            0x000000010f5176fa -[CKOperation _handleCompletionCallback:] + 148
    14  CloudKit                            0x000000010f51e521 -[CKQueryOperation _handleCompletionCallback:] + 197
    15  CloudKit                            0x000000010f58d438 __82-[CKOperationCallbackManager _performCallbackForOperation:callback:errorCallback:]_block_invoke + 288
    16  libdispatch.dylib                   0x000000011189e725 _dispatch_block_async_invoke2 + 83
    17  libdispatch.dylib                   0x0000000111890db5 _dispatch_client_callout + 8
    18  libdispatch.dylib                   0x0000000111898225 _dispatch_lane_serial_drain + 778
    19  libdispatch.dylib                   0x0000000111898ed0 _dispatch_lane_invoke + 477
    20  libdispatch.dylib                   0x00000001118a2ea3 _dispatch_workloop_worker_thread + 733
    21  libsystem_pthread.dylib             0x0000000111c79611 _pthread_wqthread + 421
    22  libsystem_pthread.dylib             0x0000000111c793fd start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

我很确定缺陷的代码是以下一组代码,该代码在视图控制器集合视图中更新UI。

以下代码崩溃(async(

    DispatchQueue.main.async {
        self.delegate?.updateActionFigureSpecificsModel()
    }

以下代码不会崩溃(同步(

    DispatchQueue.main.sync {
        self.delegate?.updateActionFigureSpecificsModel()
    }

随后的呼叫更新视图控制器收集视图

    func updateActionFigureSpecificsModel() {
        DispatchQueue.main.async {
            self.delegate?.updateActionFigureModel(forActionFigure: self, forDelegateProperty: .specifics)
        }
    }
    func updateActionFigureModel(forActionFigure actionFigure: ActionFigure, forDelegateProperty delegateProperty: DelegateProperty) {
        switch delegateProperty {
        case .specifics, .eBaySaleSummary:
            DispatchQueue.main.async {
                self.setUIActionFigure(forActionFigure: actionFigure)
            }
        }
    }
    func setUIActionFigure(forActionFigure actionFigure: ActionFigure) {
        if let indexPath = getIndexPath(forActionFigure: actionFigure) {
            DispatchQueue.main.async {
                self.collectionView.reloadItems(at: [indexPath])
            }
        }

我真的无法从您发布的确切问题中分辨出什么,但是您可能会遇到其中一个或两个一般问题:

  • 基础集合不是线程安全,不能从多个线程中修改。
  • 在迭代时无法修改地基集合。

我怀疑您正在使用的/迭代/修改您正在运行的任何线程中的集合都与您在main上派遣的任务所做的任何用途/迭代/修改碰撞。是的,我怀疑将async更改为sync只是通过等待main任务在背景线程恢复之前完成。通常,如果背景线程和主线程共享对同一基础集合的参考 - 并且其中任何一个都在修改该集合,那么您最终会遇到问题...除非您非常非常,非常小心。

我经常使用的解决方案是使我的集合分开。我的背景线程将进行更新或执行更新集合的计算。然后,我将制作收集的副本,然后将该副本传递给main进行显示和UI交互。

相关内容

最新更新