2016-05-19 21 views
2

軽量移行が失敗した場合にコアデータデータスタックを再構築しようとしており、ユーザーをログイン画面に戻しています。私はto-many関係をto-oneに変更することでこれをテストしています。コアデータの再構築/リセットエラー

最初に、新しいpersistentStoreCoordinatorを削除した後に追加するときに、同じURL(storeURL)を使用しました。しかし、 "try persistentStoreCoordinator.add ..."行のrebuildCoreData()に同じストアを2回追加できないというエラーが表示されました。

次に、新しい永続ストアのURLを変更することにしました"1"を追加することで、それはself.applicationDocumentsDirectory.URLByAppendingPathComponent( "SingleViewCoreData1.sqlite")になりました。これは正しい方向への一歩を踏み出しました。まだエラーはなく、ログイン画面に戻ることができます。しかし、ログイン後に最初の保存をしようとすると、「このNSPersistentStoreCoordinatorには永続ストアがありません(スキーマの不一致または移行の失敗)」というエラーが発生します。保存操作を実行できません。

私はここで間違っていますか?

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { 
    // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. 
    // Create the coordinator and store 
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite") 
    let options = [NSMigratePersistentStoresAutomaticallyOption: true, 
        NSInferMappingModelAutomaticallyOption: true] 
    var failureReason = "There was an error creating or loading the application's saved data." 
    do { 
     try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) 
    } catch { 
     // Report any error we got. 
     var dict = [String: AnyObject]() 
     dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
     dict[NSLocalizedFailureReasonErrorKey] = failureReason 

     dict[NSUnderlyingErrorKey] = error as NSError 
     let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 
     NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") 
     self.rebuildCoreData() 
    } 

    return coordinator 
}() 

lazy var managedObjectContext: NSManagedObjectContext = { 
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. 
    let coordinator = self.persistentStoreCoordinator 
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType) 
    managedObjectContext.persistentStoreCoordinator = coordinator 
    managedObjectContext.mergePolicy = NSRollbackMergePolicy //This policy discards in-memory state changes for objects in conflict. The persistent store’s version of the objects’ state is used 

    return managedObjectContext 
}() 

// MARK: - Tearing down core data stack and rebuilding it in the case that a lightweight migration fails 
func rebuildCoreData() { 

    let storeURL = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite") 
    do { 
     try NSFileManager.defaultManager().removeItemAtURL(storeURL) 
    } catch { 
     print(error) 
     abort() 
    } 

    for object in managedObjectContext.registeredObjects { 
     managedObjectContext.deleteObject(object) 
    } 

    do { 
     try persistentStoreCoordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: [NSMigratePersistentStoresAutomaticallyOption: true, 
      NSInferMappingModelAutomaticallyOption: true]) 
    } catch { 
     print(error) 
     abort() 
    } 

    print("successfully rebuilt core data") 
    let storyboard = UIStoryboard(name: "Main", bundle: nil) 
    let controller = storyboard.instantiateInitialViewController() 
    self.window?.rootViewController?.presentViewController(controller!, animated: false, completion: nil) 
} 

UPDATE - 変更されたファイルの削除とcatchブロックで、永続ストアコーディネータ・ロジックを編集し

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { 
    // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. 
    // Create the coordinator and store 
    var coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite") 
    let options = [NSMigratePersistentStoresAutomaticallyOption: true, 
        NSInferMappingModelAutomaticallyOption: true] 
    var failureReason = "There was an error creating or loading the application's saved data." 
    do { 
     try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) 
    } catch { 

     // Report any error we got. 
     var dict = [String: AnyObject]() 
     dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
     dict[NSLocalizedFailureReasonErrorKey] = failureReason 

     dict[NSUnderlyingErrorKey] = error as NSError 
     let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 
     NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") 

     //rebuilds core data 
     coordinator = self.rebuildCoreData(coordinator) 
    } 

    return coordinator 
}() 

新rebuildCoreDataコード:

// MARK: - Tearing down core data stack and rebuilding it in the case that a lightweight migration fails 
func rebuildCoreData(coordinator: NSPersistentStoreCoordinator) -> NSPersistentStoreCoordinator { 

    let persistentStoreParentPath = self.applicationDocumentsDirectory.path 
    let fileEnumerator = NSFileManager.defaultManager().enumeratorAtPath(persistentStoreParentPath!) 
    while let path = fileEnumerator?.nextObject() as? String { 
     if path.hasPrefix("SingleViewCoreData.sqlite") || path.hasPrefix(".SingleViewCoreData.sqlite") { 
      let pathToDelete = (persistentStoreParentPath! as NSString).stringByAppendingPathComponent(path) 
      do { 
       try NSFileManager.defaultManager().removeItemAtPath(pathToDelete) 
      } 
      catch _ { 
       // Handle error removing file 
      } 
     } 
    } 

    for object in managedObjectContext.registeredObjects { 
     managedObjectContext.deleteObject(object) 
    } 

    do { 
     let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite") 
     try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: [NSMigratePersistentStoresAutomaticallyOption: true, 
      NSInferMappingModelAutomaticallyOption: true]) 
    } catch { 
     print(error) 
     abort() 
    } 

    print("successfully rebuilt core data") 
    let storyboard = UIStoryboard(name: "Main", bundle: nil) 
    let controller = storyboard.instantiateInitialViewController() 
    self.window?.rootViewController?.presentViewController(controller!, animated: false, completion: nil) 

    return coordinator 
} 

答えて

3

CoreDataスタックは、単一のファイルから構成されていません最近のiOSバージョンではCoreDataスタックを作成し、ファイルシステムのファイル名を確認してください(具体的には.shm.walというファイルがあります)。私がファイルを消去するとき、私は通常NSFileManagerを使用して、ストアファイルの親パスのオブジェクトを列挙し、接頭辞<StoreFileName>.sqlite.<StoreFileName>.sqliteを持つものをすべて削除します。ストアファイルをサブディレクトリに置いてサブディレクトリ全体を削除することもできます。

let persistentStoreParentPath = self.applicationDocumentsDirectory.path 
let fileEnumerator = NSFileManager.defaultManager().enumeratorAtPath(persistentStoreParentPath) 
while let path = fileEnumerator?.nextObject() as? String { 
    if path.hasPrefix("SingleViewCoreData.sqlite") || path.hasPrefix(".SingleViewCoreData.sqlite") { 
     let pathToDelete = (persistentStoreParentPath as NSString).stringByAppendingPathComponent(path) 
     do { 
      try NSFileManager.defaultManager().removeItemAtPath(pathToDelete) 
     } 
     catch _ { 
      // Handle error removing file 
     } 
    } 
} 

上記のコードには、他にも考慮する必要があります。 persistentStoreCoordinatorを初期化するクロージャ内からrebuildCoreData()を呼び出していますが、persistentStoreCoordinatorにはを使用します(persistentStoreCoordinatorを使用するmanagedObjectContextにアクセスすることにより)rebuildCoreData()に直接的および間接的に使用します。

+0

サンプルコードスニペットを教えてください。 また、NSPersistentStoreCoordinatorに永続ストアがない場合、2番目のエラーはどうでしたか? –

+0

@mckamikeファイルの列挙と削除の例が必要ですか?あなたの 'CoreData'ファイルが削除された後、私は' CoreData'スタック全体を再作成します。以前に作成したコーディネーターを残しておくと、あまり節約できません。 –

+0

あなたの質問と2番目の声明にはいっていますが、どうすれば "再作成"できますか? –

関連する問題