21

我刚刚下载了新的 Xcode 7.0 beta 并从 Swift 1.2 迁移到了 Swift 2。迁移显然没有改变整个代码,实际上方法 saveContext() 很好,直到为该行抛出 2 个错误:

if moc.hasChanges && !moc.save() {

二元运算符 '&&' 不能应用于两个 Bool 操作数

call 可以抛出,但是没有标记 'try' 并且错误没有处理

该方法如下所示:

// MARK: - Core Data Saving support
func saveContext () {
    if let moc = self.managedObjectContext {
        var error: NSError? = nil
        if moc.hasChanges && !moc.save() {
            // 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.
            NSLog("Unresolved error \(error), \(error!.userInfo)")
            abort()
        }
    }
}

关于如何让它工作的任何想法?

4

2 回答 2

34

您提供的两个错误中的第一个具有误导性,但第二个是正确的。问题在于!moc.save(),从 Swift 2 开始,不再返回 Bool 而是使用 annotated throws。这意味着您必须使用try此方法以及catch它可能发出的任何异常,而不仅仅是检查其返回值是真还是假。

为了反映这一点,在 Xcode 7 中使用 Core Data 创建的新项目将生成以下样板代码,它可以替换您正在使用的代码。

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()
        }
    }
}
于 2015-06-09T13:24:49.033 回答
9

0x7fffffff 的答案是正确的,但是为了改进 Apple 的样板代码,您可以使用如下方式捕获 catch 块中的特定错误catch let error as NSError

func saveContext () {
    if managedObjectContext.hasChanges {
        do {
            try managedObjectContext.save()
        } catch let error as NSError {

            NSLog("Unresolved error \(error), \(error.userInfo)")
            // Handle Error
        }
    }
}

最好的做法是使用 varerror女巫,如果你只是这样使用它,它仍然可用:

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

同样,如果您确定managedObjectContext.save()不会throw出现exception,则代码将精简为:

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

并且推断为什么managedObjectContext在 Swift 2 代码中不是可选的,这是因为NSManagedObject(concurrencyType:)是一个不会失败的初始化程序。在 Xcode 6 中,如果为 nil,样板代码返回一个可选的上下文NSPersistentStoreCoordinator,但您可以通过检查轻松处理。

lazy var managedObjectContext: NSManagedObjectContext = {
    let coordinator = self.persistentStoreCoordinator
    var moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    moc.persistentStoreCoordinator = coordinator
    return moc
}()
于 2015-06-09T14:48:23.590 回答