在我的网络请求关闭中,我使用私有并发队列将对象插入到核心数据中,并在我调用"执行"在私人环境中。
控制台中的崩溃消息:
libc ++ abi.dylib:以NSException类型的未捕获异常终止
造成崩溃的代码:
API.sync(onlyMe, syncToken: syncToken) { success, syncResponse in
CoreDataUtils.privateContext.perform { // crashes on this line
....
}
}
我的核心数据堆栈(不幸的是现在位于AppDelegate而不是CoreDataStack类中):
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
var coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
let options = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
do {
try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)
} catch {
print(error)
}
return coordinator
}()
lazy var privateManagedObjectContext: NSManagedObjectContext = {
// Initialize Managed Object Context
var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
// Configure Managed Object Context
managedObjectContext.parent = self.managedObjectContext
return managedObjectContext
}()
lazy var managedObjectContext: NSManagedObjectContext = {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator
managedObjectContext.mergePolicy = NSRollbackMergePolicy //This policy discards in-memory state changes for objects in conflict. The persistent store’s version of the objects’ state is used
return managedObjectContext
}()
CoreDataUtils.privateContext的位置是:
class CoreDataUtils: NSObject {
static let appDel = UIApplication.shared.delegate as! AppDelegate
static let context: NSManagedObjectContext {
return appDel.managedObjectContext
}
static let privateContext: NSManagedObjectContext {
appDel.privateManagedObjectContext
}
}
答案 0 :(得分:1)
我关注了@ CodeBender的链接,发现我遇到多线程违规的几个地方。该链接提供了一种通过在项目方案中传递参数来调试并发问题的方法。这种方法可以更好地详细说明出错的地方和位置。
例如,我有一个执行提取的函数,我没有将代码包装在perform
块中。这就是我实现修复的方式:
static func searchObject(in context: NSManagedObjectContext = context, _ entity: String, key: String, value: Any) -> [NSManagedObject]? {
var objects: [NSManagedObject]?
context.performAndWait {
//searching core data for a specific attribute within an identity via a predicate
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "\(entity)")
request.returnsObjectsAsFaults = false
request.predicate = NSPredicate(format: "\(key) == %@", "\(value)")
do {
let results = try context.fetch(request)
objects = results as? [NSManagedObject]
} catch {
let nserror = error as NSError
Bugsnag.notifyError(nserror)
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
return objects
}
另外,在我从服务器插入Notification
个对象的另一个地方,我正在调用perform
块,但我没有用适当的上下文实例化托管对象。
CoreDataUtils.privateContext.perform {
for notification in notifications {
// BEFORE (WRONG) - would default to the main context (CoreDataUtils.context - see question)
//notification.insert()
// NOW (CORRECT) - inserts into private queue we are performing on
notification.insert(into: CoreDataUtils.privateContext)
}
CoreDataUtils.save()
}
我所拥有的Notification
模型中的位置:
func insert(into context: NSManagedObjectContext = CoreDataUtils.context) -> NotificationObject {
assert(CoreDataUtils.searchObject(Models.notification, key: "id", value: self.id) == nil)
let newNotification = NotificationObject(notification: self, context: managedObjectContext)
return newNotification
}