核心数据随机崩溃,可能出现并发问题

时间:2016-10-19 07:54:14

标签: ios swift core-data swift2

我有一段代码,它首先清空Core Data表,然后用新的和更新的数据填充它。此代码位于DispatchQueue.main.async块内,该块在异步请求完成后发生。这是函数的相关代码。

这是我的代码:

let queue = OperationQueue()
let deleteOperation = BlockOperation {
    let fetchRequest = Track.fetchRequest()

    let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
    batchDeleteRequest.resultType = .resultTypeCount

    do {
        try self.managedObjectContext.execute(batchDeleteRequest)
        self.managedObjectContext.reset()
    }
    catch {
        fatalCoreDataError(error)
        self.debug.log(tag: "RecentSessionsViewController", content: "Failed to delete cache")
        return
    }
}

let addOperation = BlockOperation {
    for track in tempTracks {
        let masterListEntry = NSEntityDescription.insertNewObject(forEntityName: "Track", into: self.managedObjectContext) as! Track

        masterListEntry.id = track["id"] as! NSNumber
        masterListEntry.name = track["name"] as! String
        masterListEntry.comment = track["comment"] as! String

        do {
            try self.managedObjectContext.save()

            self.trackMasterList.append(masterListEntry)
        }
        catch {
            self.debug.log(tag: "RecentSessionsViewController", content: "Core data failed")
            fatalError("Error: \(error)")
        }
    }
}

addOperation.addDependency(deleteOperation)
queue.addOperations([deleteOperation, addOperation], waitUntilFinished: false)

出于某种原因,我偶尔会在addOperation代码块上随机崩溃。在最近的崩溃中,触发了异常断点:

try self.managedObjectContext.save()

如果我点击继续,它再次落在这个断点上,然后当我再次点击继续时,它会崩溃显示汇编并出现此错误:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010c70f34b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010bd5321e objc_exception_throw + 48
    2   CoreFoundation                      0x000000010c778265 +[NSException raise:format:] + 197
    3   CoreFoundation                      0x000000010c6a762b -[__NSCFSet addObject:] + 155
    4   CoreData                            0x000000010c2427ff -[NSManagedObjectContext(_NSInternalChangeProcessing) _processPendingUpdates:] + 399
    5   CoreData                            0x000000010c23cccd -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 2445
    6   CoreData                            0x000000010c240e0c -[NSManagedObjectContext save:] + 412
    7   AppName                            0x000000010b0db7eb _TFFFFC8AppName28RecentSessionsViewController22refreshListFT_T_U_FTGSqV10Foundation4Data_GSqCSo11URLResponse_GSqPs5Error___T_U_FT_T_U0_FT_T_ + 6459
    8   AppName                            0x000000010b086987 _TTRXFo___XFdCb___ + 39
    9   Foundation                          0x000000010b8572cd __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
    10  Foundation                          0x000000010b856faf -[NSBlockOperation main] + 101
    11  Foundation                          0x000000010b8556ac -[__NSOperationInternal _start:] + 672
    12  Foundation                          0x000000010b8515ef __NSOQSchedule_f + 201
    13  libdispatch.dylib                   0x00000001134100cd _dispatch_client_callout + 8
    14  libdispatch.dylib                   0x00000001133ede6b _dispatch_queue_serial_drain + 236
    15  libdispatch.dylib                   0x00000001133eeb9f _dispatch_queue_invoke + 1073
    16  libdispatch.dylib                   0x00000001133f13b7 _dispatch_root_queue_drain + 720
    17  libdispatch.dylib                   0x00000001133f108b _dispatch_worker_thread3 + 123
    18  libsystem_pthread.dylib             0x00000001137bf746 _pthread_wqthread + 1299
    19  libsystem_pthread.dylib             0x00000001137bf221 start_wqthread + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException

在过去,我也看到它因以下错误而崩溃: “尝试递归调用-save:on context offorted”。

任何想法是怎么回事?我将这些东西包装成NSOperation块的全部原因是为了防止这种情况。显然这不起作用。这是零星的,所以我不确定它是否已经解决了。

我猜测正在发生的事情是它仍然在删除数据的过程中,当它试图写入数据时。

1 个答案:

答案 0 :(得分:1)

您没有正确执行Core Data并发。正确的方法是使用perform上的performAndWaitNSManagedObjectContext方法。像代码一样使用操作队列中的上下文是与并发相关的错误的处方。

调度队列对您没有帮助。您可以仍然使用调度队列,但您还必须使用Core Data的并发方法来避免问题。