2016-10-17 8 views
1

迅速な変換を試みています。私は速い2プロジェクトでSQLファイルからデータをプリロードしていました。迅速に3.0でこの作業を行う方法がわかりません。以下は私の迅速な2 appDelegateファイルです。スウィフト3では、コアデータのスタックが十分に変更されているため、swift 2で私と同じコードを再利用しようとするとわからないのです。私が使っていたコードは、 "SQLite preloadのために追加されました" 。あなたappDelegateのSQLファイルからSwift 3のプリロード

// MARK: - Core Data stack 

lazy var applicationDocumentsDirectory: URL = { 
    // The directory the application uses to store the Core Data store file. This code uses a directory named "self.edu.SomeJunk" in the application's documents Application Support directory. 
    let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 
    return urls[urls.count-1] 
}() 

lazy var managedObjectModel: NSManagedObjectModel = { 
    // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. 
    let modelURL = Bundle.main.url(forResource: "ESLdata", withExtension: "momd")! 
    return NSManagedObjectModel(contentsOf: modelURL)! 
}() 

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.appendingPathComponent("ESLdata.sqlite") 



    //ADDED FOR SQLITE PRELOAD 
    // Load the existing database 
    if !FileManager.default.fileExists(atPath: url.path) { 
     let sourceSqliteURLs = [Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite")!,Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-wal")!, Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-shm")!] 
     let destSqliteURLs = [self.applicationDocumentsDirectory.appendingPathComponent("ESLdata.sqlite"), self.applicationDocumentsDirectory.appendingPathComponent("ESLdata.sqlite-wal"), self.applicationDocumentsDirectory.appendingPathComponent("ESLdata.sqlite-shm")] 
     for index in 0 ..< sourceSqliteURLs.count { 
      do { 
       try FileManager.default.copyItem(at: sourceSqliteURLs[index], to: destSqliteURLs[index]) 
      } catch { 
       print(error) 
      } 
     } 
    } 
    // END OF ADDED CODE 



    var failureReason = "There was an error creating or loading the application's saved data." 
    do { 
     try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: [NSMigratePersistentStoresAutomaticallyOption:true, NSInferMappingModelAutomaticallyOption:true]) 
    } catch { 
     // Report any error we got. 
     var dict = [String: AnyObject]() 
     dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" as AnyObject? 
     dict[NSLocalizedFailureReasonErrorKey] = failureReason as AnyObject? 

     dict[NSUnderlyingErrorKey] = error as NSError 
     let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 
     // Replace this 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 \(wrappedError), \(wrappedError.userInfo)") 
     abort() 
    } 

    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 
    return managedObjectContext 
}() 

// MARK: - Core Data Saving support 

func saveContext() { 
    if managedObjectContext.hasChanges { 
     do { 
      try managedObjectContext.save() 
      print("SAVED") 
     } catch { 
      print("Save Failed") 

      let nserror = error as NSError 
      NSLog("Unresolved error \(nserror), \(nserror.userInfo)") 
      abort() 
     } 
    } 
} 

ありがとう次は私がコードにを更新しようとしましたが、運がなかったものです:あなたが行ったall--変更の

func getDocumentsDirectory()-> URL { 
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 
    let documentsDirectory = paths[0] 
    return documentsDirectory 
} 

// MARK: - Core Data stack 

lazy var persistentContainer: NSPersistentContainer = { 
    /* 
    The persistent container for the application. This implementation 
    creates and returns a container, having loaded 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. 
    */ 





    let container = NSPersistentContainer(name: "ESLdata") 
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in 
     if let error = error as NSError? { 
      // Replace this implementation with code to handle the error appropriately. 
      // fatalError() 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. 

      /* 
      Typical reasons for an error here include: 
      * The parent directory does not exist, cannot be created, or disallows writing. 
      * The persistent store is not accessible, due to permissions or data protection when the device is locked. 
      * The device is out of space. 
      * The store could not be migrated to the current model version. 
      Check the error message to determine what the actual problem was. 
      */ 
      fatalError("Unresolved error \(error), \(error.userInfo)") 
     } 
     //ADDED FOR SQLITE PRELOAD 

     let url = self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite") 
     // Load the existing database 

     if !FileManager.default.fileExists(atPath: url.path) { 
      let sourceSqliteURLs = [Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite")!,Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-wal")!, Bundle.main.url(forResource: "ESLdata", withExtension: "sqlite-shm")!] 
      let destSqliteURLs = [self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite"), self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite-wal"), self.getDocumentsDirectory().appendingPathComponent("ESLdata.sqlite-shm")] 
      for index in 0 ..< sourceSqliteURLs.count { 
       do { 
        try FileManager.default.copyItem(at: sourceSqliteURLs[index], to: destSqliteURLs[index]) 
       } catch { 
        print(error) 
       } 
      } 
     } 
     // END OF ADDED CODE 


    }) 
    return container 
}() 

// MARK: - Core Data Saving support 

func saveContext() { 
    let context = persistentContainer.viewContext 
    if context.hasChanges { 
     do { 
      try context.save() 
     } catch { 
      // Replace this implementation with code to handle the error appropriately. 
      // fatalError() 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 
      fatalError("Unresolved error \(nserror), \(nserror.userInfo)") 
     } 
    } 
} 
+0

具体的に何が問題になりましたか?あなたは運がないと言っても、あなたが抱えている問題は説明できません。 –

+0

アプリが実行されます。しかし、それは迅速に行ったようにデータをプリロードしていません2 – Viper827

+0

私のアプリではコアデータを使い果たし、初期データはCSVファイルから得られます。だから、アプリケーションが最初に実行されるたびにCSVファイルを解析するのではなく、一度解析してそれらのファイルを直接取得し、アプリケーションデリゲートを使ってロードしていました。 – Viper827

答えて

0

まず、部分的にしかスウィフト約3です。 NSPersistentContainerを使用する必要はありません。Swift 3を使用するのとは全く異なる問題です。Swift 2と同じコアデータクラスとメソッドを使用できますが、構文は異なります。古いコードを理解していれば、同じ論理とクラスを維持する方が良いでしょうが、より新しい構文を使用するほうがよいでしょう。

あなたはNSPersistentContainerにスイッチを行う場合、loadPersistentStores方法は、あなたの古いコードでaddPersistentStore呼び出しに多かれ少なかれ匹敵します。そのメソッドを呼び出すと、永続ストアファイルがロードされるため、そのデータを使用する必要があります。以前のコードでは、永続ストアをロードする前に事前ロードされたデータをコピーしますが、新しいコードでは後で実行します。だからあなたはデータを見ていないのです。

NSPersistentContainerと同じ既定のストアファイル名を使用しているようですので、それで十分でしょう。それでもデータが見つからない場合は、NSPersistentStoreDescriptionを作成して、コンテナにストアファイルを配置する場所を伝える必要があります。

もし私があなただったら、私は古いアプローチと新しいSwift 3の構文に固執します。

+0

私は最新の最新の新しい方法に切り替える方が好きです。しかし、あなたが私に指摘した方向に行くと、私はそれを理解することができました:-) – Viper827

3

これは私が探していた解決策のようです。私が今までに知る限り、それは機能します。 iOS10用の新しいスリムフォーマットコアデータスタックを採用しています。

func getDocumentsDirectory()-> URL { 
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 
    let documentsDirectory = paths[0] 
    return documentsDirectory 
} 

// MARK: - Core Data stack 

lazy var persistentContainer: NSPersistentContainer = { 

    let container = NSPersistentContainer(name: "ESLdata") 

    let appName: String = "ESLdata" 
    var persistentStoreDescriptions: NSPersistentStoreDescription 

    let storeUrl = self.getDocumentsDirectory().appendingPathComponent("ESLData.sqlite") 

    if !FileManager.default.fileExists(atPath: (storeUrl.path)) { 
     let seededDataUrl = Bundle.main.url(forResource: appName, withExtension: "sqlite") 
     try! FileManager.default.copyItem(at: seededDataUrl!, to: storeUrl) 
    } 

    let description = NSPersistentStoreDescription() 
    description.shouldInferMappingModelAutomatically = true 
    description.shouldMigrateStoreAutomatically = true 
    description.url = storeUrl 

    container.persistentStoreDescriptions = [description] 

    container.loadPersistentStores(completionHandler: { (storeDescription, error) in 
     if let error = error as NSError? { 

      fatalError("Unresolved error \(error), \(error.userInfo)") 
     } 
    }) 
    return container 
}() 
関連する問題