添加新联系人后未调用controllerDidChangeContext

时间:2016-04-23 21:51:37

标签: swift core-data nsmanagedobjectcontext

基本上看起来我的NSFetchedResultsController没有检测到变化,所以我甚至不认为这里创建的新对象正在保存。

else if segue.identifier == "AddContact" {
        let navigationController = segue.destinationViewController as! UINavigationController
        let addViewController = navigationController.topViewController as! NewContactViewController
        let contactEntity = NSEntityDescription.entityForName("Contact", inManagedObjectContext: context)
        let newContact = Contact(entity: contactEntity!, insertIntoManagedObjectContext: context)

        addViewController.contact = newContact
        addViewController.context = newContact.managedObjectContext
        addViewController.delegate = self
    }

在用户按下完成后返回联系人列表视图后,将根据我创建的代理调用此视图。

func didFinishViewController(viewController:NewContactViewController, didSave:Bool) {

    // 1
    if didSave {
        // 2
        let context = viewController.context
        context.performBlock({ () -> Void in
            if context.hasChanges {
                do {
                    try context.save()
                } catch {
                    let nserror = error as NSError
                    print("Error: \(nserror.localizedDescription)")
                    abort()
                }
            }

            // 3
            self.coreDataStack.saveContext()
        })
    }

在检查了上下文的数百万时间后,他们总是匹配,因此推送工作正常,但似乎记录了更改。 CoreDataStack.swift就是这样。

//exablishes the directory to be used for the stack in SQLite fashion
private lazy var applicationDocumentsDirectory: NSURL = {
    let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    return urls[urls.count-1]
}()

//establishes the object model that interacts with the GUI object data model
private lazy var managedObjectModel: NSManagedObjectModel = {
    let modelURL = NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

//establishes the coordinator that connects the managed context with the persistent store
private lazy var psc: NSPersistentStoreCoordinator = { let coordinator = NSPersistentStoreCoordinator(
    managedObjectModel: self.managedObjectModel)

    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent(self.modelName + ".sqlite")

    do {
        let options = [NSMigratePersistentStoresAutomaticallyOption : true]

        try coordinator.addPersistentStoreWithType( NSSQLiteStoreType, configuration: nil, URL: url, options: nil) //establishes the actual persistent store
    } catch {
        print("Error adding persistent store.")
    }
    return coordinator
}()


//establishes the managed context by which managed objects interact in reading and writing
lazy var context: NSManagedObjectContext = {
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = self.psc
    return managedObjectContext
}()

func saveContext () {
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            let nserror = error as NSError
            print("Error: \(nserror.localizedDescription)")
            abort()
        }
    }
}

NSFetchedResultsController实现

// MARK: Fetched Results controller
func contactListFetchedResultsController()-> NSFetchedResultsController {

    fetchedResultController = NSFetchedResultsController(fetchRequest: contactListFetchRequest(), managedObjectContext: coreDataStack.context, sectionNameKeyPath: nil, cacheName: nil)
    fetchedResultController.delegate = self

    do {
        try fetchedResultController.performFetch()
    } catch let error as NSError {
        print("Error: \(error.localizedDescription)")
        abort()
    }

        return fetchedResultController
}

func contactListFetchRequest() -> NSFetchRequest {

    let fetchRequest = NSFetchRequest(entityName: "Contact")
    fetchRequest.fetchBatchSize = 20

    let sortDescriptor = NSSortDescriptor(key: "firstName", ascending: true)

    fetchRequest.sortDescriptors = [sortDescriptor]

    return fetchRequest
}

2 个答案:

答案 0 :(得分:1)

为什么当你已经在UI线程上时,你有context.performBlock?您是否有多个与您合作的环境?

假设您正在使用多个上下文,则将子上下文之前的主上下文保存为performBlock(),同时导致子上下文在调用{{1}之后保存 }}

由于这是与UI相关的所有代码,因此您最好只使用整个用户界面的主队列上下文,并且我怀疑您的self.coreDataStack.saveContext()将开始接收通知。

答案 1 :(得分:0)

看来你还没有实现NSFetchedresultsControllerDelegate方法:

func controllerWillChangeContent(controller: NSFetchedResultsController) {
    tableView.beginUpdates()
}

func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {
    switch type {
    case .Insert:
        tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Automatic)
    case .Delete:
        tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: .Automatic)
    case .Move, .Update:
        break
    }
}

func controller(controller: NSFetchedResultsController, didChangeObject anObject: NSManagedObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    switch type {
    case .Insert:
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
    case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
    case .Update:
        tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
    case .Move:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Automatic)
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Automatic)
    }
}

func controllerDidChangeContent(controller: NSFetchedResultsController) {
    tableView.endUpdates()
}