Подтвердить что ты не робот

Сдвиг 2 миграции saveContext() в appDelegate

Я только что загрузил новую бета-версию Xcode 7.0 и сделал переход от Swift 1.2 к Swift 2. Миграция, по-видимому, не изменила весь код, на самом деле метод saveContext(), который был в порядке, пока не набросал 2 ошибки для строки

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

Двоичный оператор && не может применяться к двум операндам Bool

и

Вызов может вызывать, но он не отмечен "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()
        }
    }
}

Любые идеи о том, как заставить его работать?

4b9b3361

Ответ 1

Первая из двух ошибок, которые вы указали, вводит в заблуждение, а вторая - на месте. Проблема в !moc.save(), которая с Swift 2 больше не возвращает Bool и вместо этого аннотируется 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()
        }
    }
}

Ответ 2

Ответ на 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
        }
    }
}

Лучшей практикой является использование var error, ведьма все равно будет доступна, если вы просто используете ее следующим образом:

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

Таким же образом, если вы уверены, что managedObjectContext.save() не будет throw a exception, код будет уменьшен до:

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

И чтобы экстраполяция на то, почему managedObjectContext не является необязательным в коде Swift 2, это потому, что NSManagedObject(concurrencyType:) является инициализатором, который не прерывается. В Xcode 6 код шаблона возвратил необязательный контекст, если NSPersistentStoreCoordinator равен нулю, но вы можете легко справиться с этим, проверив.

lazy var managedObjectContext: NSManagedObjectContext = {
    let coordinator = self.persistentStoreCoordinator
    var moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    moc.persistentStoreCoordinator = coordinator
    return moc
}()