2017-01-13 22 views
0

nilを返しますフェッチ以下の更新を参照してください:swift3 CoreDataは

あり、これに類似した質問の数がありますが、どれも私のために十分に答えているように見えるんので、任意の助けが理解されるであろう。

私は別のアプリケーションで作成したプリロードされたデータベースを持っています。これが初めて実行される場合、データベースは文書ディレクトリーにコピーされます。 Iデータベースが期待される位置にあることをログから見ることができます:

AppDelegate urls: [file:///Volumes/HD1%20-%20DATA/Users/david/Library/Developer/CoreSimulator/Devices/8B0E16F5-B739-4299-9B4D-E6A3C8C92E55/data/Containers/Data/Application/B8A87853-6FEB-4532-83EF-AB08985F2B43/Documents/] 

たSQLiteManagerを使用することにより、私は、予想通り、データベースにデータを保持していることを確認することができます。

enter image description here

マイCoreDataオブジェクトグラフは次のとおりです。ただし

enter image description here

、私はフェッチ要求を実行すると、結果はnilです。

func testLetters() { 
     print(#function) 

     let moc = coreDataStack.persistentContainer.viewContext 
     let letterFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "LetterEntity") 

     do { 
      let fetchedLetters = try moc.fetch(letterFetch) as! [LetterEntity] 
      print(#function, "letter: ", fetchedLetters) 
     } catch { 
      fatalError("Failed to fetch employees: \(error)") 
     } 
} 

私はコアデータは以下のように見える私のアプリの委任の外にスタックがあります:

import UIKit 
import CoreData 
class CoreDataStack { 

    static let instance = CoreDataStack() 

    lazy var persistentContainer: NSPersistentContainer = { 
     let container = NSPersistentContainer(name: "GuessGreek") 

     let directoryUrls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 

     let applicationDocumentDirectory = directoryUrls[0] 

     let storeUrl = applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite") 

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

       fatalError("Unresolved error \(error), \(error.userInfo)") 
      } 
     }) 
     return container 
    }() 



    func saveContext() { 
     let context = persistentContainer.viewContext 
     if context.hasChanges { 
      do { 
       try context.save() 
      } catch let error as NSError { 
       fatalError("Unresolved error \(error), \(error.userInfo)") 
      } 
     } 
    } 
} 

は再び、任意のヘルプは歓迎されるでしょう

これはフェッチ要求です。

let directoryUrls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask) 

let applicationDocumentDirectory = directoryUrls[0] 

let managedContext = coreDataStack.persistentContainer.viewContext 

let storeUrl = applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite") 

print("AppDelegate", #function, "StoreURL", storeUrl) 


if !FileManager.default.fileExists(atPath: (storeUrl.path)) { 
    print("Copying databases...") 

    let sourceSqliteURLs = [ 
     Bundle.main.url(forResource: "GuessGreekDatabase", withExtension: "sqlite")!, 
     Bundle.main.url(forResource: "GuessGreekDatabase", withExtension: "sqlite-wal")!, 
     Bundle.main.url(forResource: "GuessGreekDatabase", withExtension: "sqlite-shm")!] 

    let destSqliteURLs = [ 
     applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite"), 
     applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite-wal"), 
     applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite-shm")] 

    for index in 0..<sourceSqliteURLs.count { 
     do { 
      try FileManager.default.copyItem(at: sourceSqliteURLs[index], to: destSqliteURLs[index]) 
      print(#function, "Done copying") 
     } catch { 
      print(error) 
     } 


     do { 
      try managedContext.save() 
     } catch let error as NSError { 
      print("Error While Saving Data: \(error.userInfo)") 
     } 
    } 
} 

私はSIMからアプリを削除して、クリーン:

UPDATEは、次のように私は、データベースのコピーを変更しました。私が走ると、ファイルがすでに存在するのでコピーできないというエラーが出ています...私はここで何かを逃しています。

答えて

1

NSPersistentContainerは、ドキュメントディレクトリではなく、デフォルトでApplication Supportディレクトリを使用します。

loadPersistentStores完了ブロックにstoreURLの値を出力すると、アプリケーションサポートを指していることがわかります。起こっていることは、作成したコピーを無視して、モデルに基づいて空のデータベースを作成していることです。

代わりにアプリケーションサポートにコピーするか、の処理を制御する場合は、NSPersistentStoreDescriptionオブジェクトをドキュメントディレクトリを指すURLで渡します。

それは、これらの行ということは注目に値します:

let directoryUrls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) 

let applicationDocumentDirectory = directoryUrls[0] 

let storeUrl = applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite") 

は、あなたの現在のコードでは絶対に何もしていません。

SQLiteManagerのスクリーンショットには、ファイルがGuessGreekDatabase.sqliteと表示されていますが、NSPersistentContainerのデフォルトのストア名はGuessGreek.sqliteであるため、コピー中に修正が必要な場合もあります。

+0

ありがとうございます!正しいSQLiteManagerのスクリーンショットで質問を更新しました。ディレクトリ名を修正します。 –

+0

あなたをバグして申し訳ありません。私は自分のコードサンプルを私の質問で更新しました。より多くの洞察力 - または私のコードの代わりに...素晴らしいだろう。 –

+1

私はあなたが私を問題/解決に導いたときにこれを解決しているとマークしています。私はソースにもっと注意を払わなければならず、ディレクトリを受け取らなければならなかった。再度、感謝します –