web-dev-qa-db-ja.com

Swift appDelegateの2つの移行saveContext()

新しいXcode 7.0ベータ版をダウンロードし、Swift 1.2からSwift 2.に移行しました。移行によってコード全体が変更されたようには見えません行に2つのエラーをスローするまで問題なかったsaveContext()メソッド:

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

二項演算子 '&&'は2つのブールオペランドに適用できません

そして

呼び出しはスローできますが、 '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()
        }
    }
}

それを機能させる方法に関するアイデアはありますか?

21
kalafun

指定した2つのエラーのうち最初のエラーは誤解を招く可能性がありますが、2番目のエラーは問題の原因です。問題は!moc.save()にあります。これはSwift 2以降、Boolを返さなくなり、代わりにthrowsと注釈が付けられます。つまり、tryこのメソッドとcatchは、戻り値がtrueまたはfalseであるかどうかを確認するだけでなく、発生する可能性のある例外をすべて処理します。

これを反映するために、Core Dataを使用してXcode 7で作成された新しいプロジェクトは、使用しているコードを置き換えることができる次のボイラープレートコードを生成します。

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()
        }
    }
}
34
Mick MacCallum

0x7fffffffによる答えは正しいですが、Appleのボイラープレートコードを改善するには、次のように_catch let error as NSError_を使用して、catchブロックで特定のエラーをキャッチできます。

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

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

ベストプラクティスは、変数errorを使用することです。この方法で使用する場合は、引き続き使用できます。

_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()
     }
}
_

また、Swift 2コードでmanagedObjectContextがオプションではない理由を推定すると、NSManagedObject(concurrencyType:)が失敗しない初期化子であるためです。 Xcode 6では、NSPersistentStoreCoordinatorがnilの場合、ボイラープレートコードはオプションのコンテキストを返しましたが、これをチェックすることで簡単に処理できます。

_lazy var managedObjectContext: NSManagedObjectContext = {
    let coordinator = self.persistentStoreCoordinator
    var moc = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    moc.persistentStoreCoordinator = coordinator
    return moc
}()
_
9
Ian