Swift — помощь в расшифровке стека вызовов

#swift #crash #stack

#быстрый #авария #стек #swift #сбой

Вопрос:

Я хотел бы знать, есть ли что-нибудь в стеке сбоев, что поможет мне добраться до корня «Коллекция <__NSCFSet: 0x600000986940> была изменена при перечислении». ошибка. Из того, что я узнал до сих пор, вызов контекста сохранения во время перечисления может вызвать эту проблему. Хотя я думал, что использование .main.async исправит это. Это не так. Я думаю, мне нужно выяснить, как реализовать параллелизм, но сначала я просто хотел бы знать, где возникает проблема.

 0   CoreFoundation                      0x0000000106c4f6fb __exceptionPreprocess   331
    1   libobjc.A.dylib                     0x0000000105c72ac5 objc_exception_throw   48
    2   CoreFoundation                      0x0000000106c4c5cc __NSFastEnumerationMutationHandler   124
    3   CoreData                            0x00000001065c688f -[NSManagedObjectContext executeFetchRequest:error:]   2463
    4   ncdrainage                          0x0000000104f18e64 $s10ncdrainage15ApplicationDataC18deleteLocalRecords04listF7DeletedySDyS2SG_tF   1572
    5   ncdrainage                          0x0000000104f106db $s10ncdrainage15ApplicationDataC15downloadUpdates13finishClosureyySo23UIBackgroundFetchResultVc_tFySo19CKServerChangeTokenCSg_Sbs5Error_pSgtcfU1_ySo14CKRecordZoneIDC_AJ10Foundation0C0VSgSbALtcfU2_   1115
    6   ncdrainage                          0x0000000104f2f09b $s10ncdrainage15ApplicationDataC15downloadUpdates13finishClosureyySo23UIBackgroundFetchResultVc_tFySo19CKServerChangeTokenCSg_Sbs5Error_pSgtcfU1_ySo14CKRecordZoneIDC_AJ10Foundation0C0VSgSbALtcfU2_TA   59
    7   ncdrainage                          0x0000000104f109a4 $sSo14CKRecordZoneIDCSo19CKServerChangeTokenCSg10Foundation4DataVSgSbs5Error_pSgIeggggyg_AbESo6NSDataCSgSbSo7NSErrorCSgIeyByyyyy_TR   372
    8   CloudKit                            0x00000001054f26a7 -[CKFetchRecordZoneChangesOperation _handleProgressCallback:]   4864
    9   CloudKit                            0x00000001054ba54f -[CKOperation _handleProgressCallback:completion:]   61
    10  CloudKit                            0x00000001054b6d3c __21-[CKOperation _start]_block_invoke.370   216
    11  CloudKit                            0x00000001055306c5 __68-[CKOperationCallbackManager _performCallbackForOperation:callback:]_block_invoke   278
    12  libdispatch.dylib                   0x000000010922d725 _dispatch_block_async_invoke2   83
    13  libdispatch.dylib                   0x000000010921fdb5 _dispatch_client_callout   8
    14  libdispatch.dylib                   0x0000000109227225 _dispatch_lane_serial_drain   778
    15  libdispatch.dylib                   0x0000000109227ed0 _dispatch_lane_invoke   477
    16  libdispatch.dylib                   0x0000000109231ea3 _dispatch_workloop_worker_thread   733
    17  libsystem_pthread.dylib             0x0000000109608611 _pthread_wqthread   421
    18  libsystem_pthread.dylib             0x00000001096083fd start_wqthread   13
  

Комментарии:

1. Правильно обозначьте свой отчет о сбое, чтобы вы могли видеть, где в вашем собственном коде происходит сбой.

2. Но, похоже, проблема в чем-то, что называется deleteLocalRecords .

Ответ №1:

Это не столько то, что есть в вашем стеке сбоев, сколько то, чего там нет. Поскольку нет ничего подобного NSManagedObjectContextPerform , кажется, что вы не работаете с вашим контекстом в правильном потоке. Вы должны вызвать код, работающий с контекстом, из блока, отправленного в NSManagedObjectContext::perform или NSManagedObjectContext::performAndWait.

Итак, код должен быть примерно таким:

 func deleteObjects(context: NSManagedObjectContext) {
    context.perform {
        let objects = context.fetch(fetchRequest)
        for object in objects {
            context.delete(object)
        }

        context.save()
    }
}
  

Вы можете выявить такие проблемы при отладке, включив отладку параллелизма основных данных.

Комментарии:

1. Спасибо за ответ. Итак, если я создам контекст управляемого объекта, используя privateQueueConcurrencyType, а затем вызову его, как показано в примере выше, я должен быть хорошим? Или, по крайней мере, на правильном пути?

2. @squarehippo10 Вы должны быть хороши в том смысле, что контекстные операции не будут вызывать странные сбои из-за многопоточности, но все еще может потребоваться больше работы для синхронизации изменений данных и пользовательского интерфейса и тому подобного.