Swift 2 migration saveContext() in appDelegate

后端 未结 2 1549
执笔经年
执笔经年 2020-12-15 05:11

I have just downloaded the new Xcode 7.0 beta and did a migration from Swift 1.2 to Swift 2. The migration apparently did not change the whole code, in fact a method saveCon

相关标签:
2条回答
  • 2020-12-15 06:02

    The first of the two errors you provided is misleading, but the second is spot on. The problem is in !moc.save() which as of Swift 2, no longer returns Bool and is instead annotated throws. This means that you you have to try this method and catch any exceptions that it may emit, instead of just checking wether its return value is true or false.

    To reflect this, a new project created in Xcode 7 using Core Data will produce the following boilerplate code which can replace the code you're using.

    func saveContext () {
        if managedObjectContext.hasChanges {
            do {
                try managedObjectContext.save()
            } catch {
                // Replace this implementation 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.
                let nserror = error as NSError
                NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
                abort()
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-15 06:03

    The answer by 0x7fffffff is correct, but to improve upon Apple's boilerplate code, you can catch the specific error in the catch block using catch let error as NSError like so:

    func saveContext () {
        if managedObjectContext.hasChanges {
            do {
                try managedObjectContext.save()
            } catch let error as NSError {
    
                NSLog("Unresolved error \(error), \(error.userInfo)")
                // Handle Error
            }
        }
    }
    

    The best practice is to use the var error witch will still be available if you just use it this way :

    func saveContext () {
            if managedObjectContext.hasChanges {
                do {
                    try managedObjectContext.save()
                } catch {
                    NSLog("Unresolved error \(error), \(error.userInfo)")
                    // Handle Error
                }
            }
        }
    

    In the same way, if you are sure that managedObjectContext.save() will not throw an exception, the code is slimmed down to:

    func saveContext () {
         if managedObjectContext.hasChanges {
            try! managedObjectContext.save()
         }
    }
    

    And to extrapolate on why managedObjectContext is not optional in the Swift 2 code, it is because the NSManagedObject(concurrencyType:) is an initializer that does not fail. In Xcode 6, the boilerplate code returned an optional context if the NSPersistentStoreCoordinator is nil, but you can handle this easily by checking.

    lazy var managedObjectContext: NSManagedObjectContext = {
        let coordinator = self.persistentStoreCoordinator
        var moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
        moc.persistentStoreCoordinator = coordinator
        return moc
    }()
    
    0 讨论(0)
提交回复
热议问题