核心数据与libc ++ abi.dylib冲突:以NSException类型的未捕获异常终止

时间:2018-02-06 20:20:42

标签: ios swift core-data

当我尝试将新对象保存到核心数据中时,当我尝试保存上下文时,我收到此错误并崩溃:

libc++abi.dylib: terminating with uncaught exception of type NSException

我使用相同的方法将新创建的托管对象保存在许多其他视图控制器中,除此之外所有工作正常。当我改变这一行时,问题就出现了:

var managedObjectContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)

来自AppDelegate中的.mainQueueConcurrencyType。

这是我在AppDel中的持久存储协调器设置:

    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
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.appendingPathComponent("SingleViewCoreData.sqlite")
    let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
    var failureReason = "There was an error creating or loading the application's saved data."
    do {
        try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options)
    } catch {
        // Report any error we got.
        var dict = [String: AnyObject]()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject?
        dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject?

        dict[NSUnderlyingErrorKey] = error as NSError
        let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
        // Replace this with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
        abort()
    }

    return coordinator
}()

这是导致崩溃的一系列功能:

//get a new model for the components, same context, new FRC
    purchaseOrderModel = StockModel()
    purchaseOrderModel.setupManagedObjectContext()
    purchaseOrderModel.tableView = tableView

    if purchaseOrder == nil {
        //delegate?.editModeStateChange(editing: true)
        purchaseOrder = purchaseOrderModel.savePurchaseOrderWith("", supplier: nil, issueDate: Date(), deliveryDate: Date(), deliveryStatus: false)
        delegate?.newItemAdded()
        creatingNewPurchaseOrder = true
    }

致电

 func savePurchaseOrderWith(_ poId: String?, supplier: NSManagedObject?, issueDate: Date, deliveryDate: Date, deliveryStatus: Bool? = nil) -> NSManagedObject {

    let newPurchaseOrder = NSEntityDescription.insertNewObject(forEntityName: "Purchase_Order", into: context)

    newPurchaseOrder.setValue(poId, forKey: "po_id")
    newPurchaseOrder.setValue(issueDate, forKey: "issue_date")
    newPurchaseOrder.setValue(deliveryDate, forKey: "est_delivery_date")
    newPurchaseOrder.setValue(supplier, forKey: "supplier")
    newPurchaseOrder.setValue(deliveryStatus, forKey: "delivered")

    _ = doSaveContext()

    return newPurchaseOrder
}

doSaveContext:

    func doSaveContext() -> Bool {
    do {
        try context.save() //editing POs makes it crash here after changing the created context in app delegate
        return true
    } catch let error as NSError {
        print("Error saving context after delete \(error.localizedDescription)")
        return false
    }
}

我在try context.save()

上获得了一个SIGBART

自从我参与这个项目以来已经过了几个月,但这就是停止开发的基础,所以帮助会很棒。奇怪的是,创建一个以doSaveContext()结尾的新空对象(比如交付,新产品等)的每个其他路径都可以正常工作。

很高兴发布额外信息等。

更新1:添加异常断点时,它在我的模型类的这个函数中断开:

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch type{
        case NSFetchedResultsChangeType.insert:
            //note that for insert we insert a row at _newIndexPath_
            if let insertIndexPath = newIndexPath {
                self.tableView.insertRows(at: [insertIndexPath], with: UITableViewRowAnimation.fade)
            }
        case NSFetchedResultsChangeType.delete:
            //note that for delete we delete the row at _indexPath_
            if let deleteIndexPath = indexPath {
                self.tableView.deleteRows(at: [deleteIndexPath], with: UITableViewRowAnimation.fade)
            }
        case NSFetchedResultsChangeType.update:
            //note that for update we update the row at _indexPath_
            if indexPath != nil {
//                let cell = self.tableView.cellForRowAtIndexPath(updateIndexPath)
//                let supplier = fetchedResultsController.objectAtIndexPath(updateIndexPath)
//                cell!.textLabel?.text = supplier.name
            }
        case NSFetchedResultsChangeType.move:
            //note that for Move we delete the row at _indexPath_
            if let deleteIndexPath = indexPath {
                self.tableView.insertRows(at: [deleteIndexPath], with: UITableViewRowAnimation.fade)
            }
            //note that for move we insert a row at _newIndexPath_
            if let insertIndexPath = newIndexPath {
                self.tableView.insertRows(at: [insertIndexPath], with: UITableViewRowAnimation.fade)
            }
        }
    }
如果有帮助,请在self.tableView.insertRows(at: [insertIndexPath], with: UITableViewRowAnimation.fade)行上

。无法在任何地方找到明确的日志。

更新2:在控制台中断时键入bt会产生以下结果:

(lldb) bt
* thread #1, queue = 'NSManagedObjectContext 0x6040003cb8b0', stop reason = breakpoint 1.2
    frame #0: 0x000000010c8e3b86 libc++abi.dylib`__cxa_throw
    frame #1: 0x0000000106ee2068 libobjc.A.dylib`objc_exception_throw + 343
    frame #2: 0x0000000107ff8362 CoreFoundation`+[NSException raise:format:arguments:] + 98
    frame #3: 0x0000000106986089 Foundation`-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
    frame #4: 0x00000001096d9430 UIKit`-[UITableView _endCellAnimationsWithContext:] + 18124
    frame #5: 0x00000001096f5524 UIKit`-[UITableView _updateRowsAtIndexPaths:withUpdateAction:rowAnimation:usingPresentationValues:] + 1342
    frame #6: 0x00000001096f55f7 UIKit`-[UITableView insertRowsAtIndexPaths:withRowAnimation:] + 118
  * frame #7: 0x00000001062013fd SC Dev`StockModel.controller(controller=0x00006000000efe00, anObject=Any @ 0x00007fff59ae7458, indexPath=nil, type=insert, newIndexPath=2 indices, self=0x0000600000478940) at StockModel.swift:283
    frame #8: 0x0000000106201f30 SC Dev`@objc StockModel.controller(_:didChange:at:for:newIndexPath:) at StockModel.swift:0
    frame #9: 0x0000000107b6ef17 CoreData`__82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 5767
    frame #10: 0x0000000107a13bf8 CoreData`developerSubmittedBlockToNSManagedObjectContextPerform + 168
    frame #11: 0x000000010cccb43c libdispatch.dylib`_dispatch_client_callout + 8
    frame #12: 0x000000010ccd2338 libdispatch.dylib`_dispatch_queue_barrier_sync_invoke_and_complete + 392
    frame #13: 0x0000000107a13afe CoreData`-[NSManagedObjectContext performBlockAndWait:] + 286
    frame #14: 0x0000000107b6d877 CoreData`-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:] + 119
    frame #15: 0x0000000107f8f07c CoreFoundation`__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    frame #16: 0x0000000107f8ef7a CoreFoundation`_CFXRegistrationPost + 442
    frame #17: 0x0000000107f8ecc2 CoreFoundation`___CFXNotificationPost_block_invoke + 50
    frame #18: 0x0000000107f50a32 CoreFoundation`-[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1826
    frame #19: 0x0000000107f4fbac CoreFoundation`_CFXNotificationPost + 652
    frame #20: 0x00000001068c3842 Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    frame #21: 0x00000001079fcbd5 CoreData`-[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 773
    frame #22: 0x0000000107a9e0ca CoreData`-[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1658
    frame #23: 0x00000001079f6f0f CoreData`-[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 2399
    frame #24: 0x00000001079fa7d3 CoreData`-[NSManagedObjectContext save:] + 419
    frame #25: 0x00000001062032fc SC Dev`StockModel.doSaveContext(self=0x0000600000673000) at StockModel.swift:381
    frame #26: 0x000000010620affd SC Dev`StockModel.savePurchaseOrderWith(poId="", supplier=nil, issueDate=2018-02-06 21:17:37 UTC, deliveryDate=2018-02-06 21:17:37 UTC, deliveryStatus=false, self=0x0000600000673000) at StockModel.swift:592
    frame #27: 0x000000010626ce76 SC Dev`PurchaseOrderDetailViewController.viewDidLoad(self=0x00007f941e038800) at PurchaseOrderDetailViewController.swift:68
    frame #28: 0x0000000106270f84 SC Dev`@objc PurchaseOrderDetailViewController.viewDidLoad() at PurchaseOrderDetailViewController.swift:0
    frame #29: 0x000000010975ad51 UIKit`-[UIViewController loadViewIfRequired] + 1235
    frame #30: 0x00000001097a24dc UIKit`-[UINavigationController _updateScrollViewFromViewController:toViewController:] + 68
    frame #31: 0x00000001097a2818 UIKit`-[UINavigationController _startTransition:fromViewController:toViewController:] + 153
    frame #32: 0x00000001097a392f UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 841
    frame #33: 0x00000001097a4b90 UIKit`-[UINavigationController __viewWillLayoutSubviews] + 115
    frame #34: 0x00000001099fb2ae UIKit`-[UILayoutContainerView layoutSubviews] + 231
    frame #35: 0x000000010968b551 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1331
    frame #36: 0x00000001093fb4ba QuartzCore`-[CALayer layoutSublayers] + 153
    frame #37: 0x00000001093ff5a9 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 401
    frame #38: 0x00000001093881cd QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 365
    frame #39: 0x00000001093b3ae4 QuartzCore`CA::Transaction::commit() + 500
    frame #40: 0x00000001095e7687 UIKit`_afterCACommitHandler + 272
    frame #41: 0x0000000107f95db7 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
    frame #42: 0x0000000107f95d0e CoreFoundation`__CFRunLoopDoObservers + 430
    frame #43: 0x0000000107f7a324 CoreFoundation`__CFRunLoopRun + 1572
    frame #44: 0x0000000107f79a89 CoreFoundation`CFRunLoopRunSpecific + 409
    frame #45: 0x000000010f6de9c6 GraphicsServices`GSEventRunModal + 62
    frame #46: 0x00000001095bcd30 UIKit`UIApplicationMain + 159
    frame #47: 0x0000000106142607 SC Dev`main at AppDelegate.swift:18
    frame #48: 0x000000010cd47d81 libdyld.dylib`start + 1

更新3:将_ = doSaveContext()包裹在DispatchQueue.main.async {中让我向前走了几步,但仍然像以前一样在下面的日志中打破了同一个表插入行。

    bt
* thread #1, queue = 'NSManagedObjectContext 0x6000001da400', stop reason = breakpoint 1.1
    frame #0: 0x000000010945bf11 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x000000010a572362 CoreFoundation`+[NSException raise:format:arguments:] + 98
    frame #2: 0x0000000108f00089 Foundation`-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
    frame #3: 0x000000010b9e0430 UIKit`-[UITableView _endCellAnimationsWithContext:] + 18124
    frame #4: 0x000000010b9fc524 UIKit`-[UITableView _updateRowsAtIndexPaths:withUpdateAction:rowAnimation:usingPresentationValues:] + 1342
    frame #5: 0x000000010b9fc5f7 UIKit`-[UITableView insertRowsAtIndexPaths:withRowAnimation:] + 118
  * frame #6: 0x000000010877a0cd SC Dev`StockModel.controller(controller=0x00006000000fea00, anObject=Any @ 0x00007fff575731c8, indexPath=nil, type=insert, newIndexPath=2 indices, self=0x000060400046aa00) at StockModel.swift:283
    frame #7: 0x000000010877ac00 SC Dev`@objc StockModel.controller(_:didChange:at:for:newIndexPath:) at StockModel.swift:0
    frame #8: 0x000000010a0e8f17 CoreData`__82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 5767
    frame #9: 0x0000000109f8dbf8 CoreData`developerSubmittedBlockToNSManagedObjectContextPerform + 168
    frame #10: 0x000000010f23843c libdispatch.dylib`_dispatch_client_callout + 8
    frame #11: 0x000000010f23f338 libdispatch.dylib`_dispatch_queue_barrier_sync_invoke_and_complete + 392
    frame #12: 0x0000000109f8dafe CoreData`-[NSManagedObjectContext performBlockAndWait:] + 286
    frame #13: 0x000000010a0e7877 CoreData`-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:] + 119
    frame #14: 0x000000010a50907c CoreFoundation`__CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    frame #15: 0x000000010a508f7a CoreFoundation`_CFXRegistrationPost + 442
    frame #16: 0x000000010a508cc2 CoreFoundation`___CFXNotificationPost_block_invoke + 50
    frame #17: 0x000000010a4caa32 CoreFoundation`-[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1826
    frame #18: 0x000000010a4c9bac CoreFoundation`_CFXNotificationPost + 652
    frame #19: 0x0000000108e3d842 Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 66
    frame #20: 0x0000000109f76bd5 CoreData`-[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] + 773
    frame #21: 0x000000010a0180ca CoreData`-[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1658
    frame #22: 0x0000000109f70f0f CoreData`-[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 2399
    frame #23: 0x0000000109f747d3 CoreData`-[NSManagedObjectContext save:] + 419
    frame #24: 0x000000010877bfcc SC Dev`StockModel.doSaveContext(self=0x000060000046fec0) at StockModel.swift:381
    frame #25: 0x0000000108783ebe SC Dev`closure #1 in StockModel.savePurchaseOrderWith(self=0x000060000046fec0) at StockModel.swift:593
    frame #26: 0x0000000108783f52 SC Dev`partial apply for closure #1 in StockModel.savePurchaseOrderWith(_:supplier:issueDate:deliveryDate:deliveryStatus:) at StockModel.swift:0
    frame #27: 0x00000001086c0b89 SC Dev`thunk for @callee_owned () -> () at AddProductViewController.swift:0
    frame #28: 0x000000010f2373f7 libdispatch.dylib`_dispatch_call_block_and_release + 12
    frame #29: 0x000000010f23843c libdispatch.dylib`_dispatch_client_callout + 8
    frame #30: 0x000000010f2436f0 libdispatch.dylib`_dispatch_main_queue_callback_4CF + 628
    frame #31: 0x000000010a52fef9 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    frame #32: 0x000000010a4f4662 CoreFoundation`__CFRunLoopRun + 2402
    frame #33: 0x000000010a4f3a89 CoreFoundation`CFRunLoopRunSpecific + 409
    frame #34: 0x0000000111c579c6 GraphicsServices`GSEventRunModal + 62
    frame #35: 0x000000010b8c3d30 UIKit`UIApplicationMain + 159
    frame #36: 0x00000001086bb2d7 SC Dev`main at AppDelegate.swift:18
    frame #37: 0x000000010f2b4d81 libdyld.dylib`start + 1
(lldb) 

1 个答案:

答案 0 :(得分:1)

无法确定,但您的堆栈跟踪强烈暗示该问题与从NSFetchedResultsControllerDelegate回调更新表视图有关。从您的一条评论中,最有可能的原因是您没有在任何地方的表格视图中调用beginUpdates()

NSFetchedResultsControllerDelegate更新表格视图有两种基本方法。首先,简单但不是最佳:不要实施controllerWillChangeContent(_:)controller(_:didChange:at:for:newIndexPath:)执行实施controllerDidChangeContent(_:),但在表格视图中使用该方法reloadData()。不要打扰开始/结束更新或插入/删除/ etc行。

第二个,更好但稍微复杂一点的是所有这些:

  1. 实施controllerWillChangeContent(_:)并使用它来致电beginUpdates()
  2. 实施controller(_:didChange:at:for:newIndexPath:)以在表格中插入/更新/等行。
  3. 实施controllerDidChangeContent(_:)并使用它来致电endUpdates()
  4. “开始”和“结束”通话都至关重要。我无法100%确定这是导致您特定崩溃的原因,但我希望不让beginUpdates()导致某种崩溃。