• Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
  • Swift2.1 & Xcode7.1対応の日本語版アップルチュートリアル!
  • Table View実装チュートリアルをXcode7.2.1で解説
  • Core Data シンプルチュートリアル
  • 私の本業、オフィシャルなブログ-> Life-LOG

プロジェクト内にあるファイルをアプリに取りこんで、アプリ内にファイルを移動させる手順を学んだところです。

www.raywenderlich.com

プロジェクト作成時に「Use Core Data」のチェックマークを入れなかったら自前でCoreDataStackクラスを作る必要があることを昨日説明しました。CoreDataStackの主要プロパティは3つあります。

  1. ManagedObjectContext
  2. PersistentStoreCoordinator
  3. ManagedObjectModel

この中で、PersistentStoreCoordinatorに注目しています。

  lazy var psc: NSPersistentStoreCoordinator = {
    let coordinator = NSPersistentStoreCoordinator(
      managedObjectModel: self.managedObjectModel)
    let url =
    self.applicationDocumentsDirectory
      .URLByAppendingPathComponent(self.seedName + ".sqlite")
    
    // 1
    let bundle = NSBundle.mainBundle()
    let seededDatabaseURL = bundle
      .URLForResource(self.seedName, withExtension: "sqlite")!

    // 2
    let didCopyDatabase: Bool
    do {
      try NSFileManager.defaultManager()
        .copyItemAtURL(seededDatabaseURL, toURL: url)
      didCopyDatabase = true
    } catch {
      didCopyDatabase = false
    }

    // 3
    if didCopyDatabase {
  
      // 4
      let seededSHMURL = bundle
        .URLForResource(self.seedName, withExtension: "sqlite-shm")!
      let shmURL = self.applicationDocumentsDirectory
        .URLByAppendingPathComponent(self.seedName + ".sqlite-shm")
      do {
        try NSFileManager.defaultManager()
          .copyItemAtURL(seededSHMURL, toURL: shmURL)
      } catch {
        let nserror = error as NSError
        print("Error: (nserror.localizedDescription)")
        abort()
      }

      // 5
      let seededWALURL = bundle
        .URLForResource(self.seedName, withExtension: "sqlite-wal")!
      let walURL = self.applicationDocumentsDirectory
        .URLByAppendingPathComponent(self.seedName + ".sqlite-wal")
      do {
        try NSFileManager.defaultManager()
          .copyItemAtURL(seededWALURL, toURL: walURL)
      } catch {
        let nserror = error as NSError
        print("Error: (nserror.localizedDescription)")
        abort()
      }
      
      print("Seeded Core Data")
    }
    
    // 6
    do {
      try coordinator.addPersistentStoreWithType(
        NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
    } catch {
      //7
        let nserror = error as NSError
        print("Error: (nserror.localizedDescription)")
        abort()
    }
    
    return coordinator
    }()

アプリを起動した時にDocumentsディレクトリに何もないのでdidCopyDatabaseは「true」になっていて、「//4」のif節が実行されます。

 // 4
 let seededSHMURL = bundle
    .URLForResource(self.seedName, withExtension: "sqlite-shm")!
 let shmURL = self.applicationDocumentsDirectory
    .URLByAppendingPathComponent(self.seedName + ".sqlite-shm")
 do {
   try NSFileManager.defaultManager()
     .copyItemAtURL(seededSHMURL, toURL: shmURL)
 } catch {
   let nserror = error as NSError
   print("Error: (nserror.localizedDescription)")
   abort()
 }

ここのステップで何をしているのか?

Xcodeで用意している「SurfJournalDatabase.sqlite-shm」ファイルをアプリ内のDocumentsディレクトリ内にコピーして持ってきます。当然エラーを投げるメソッドを使用しているので失敗した時のためにエラーを「catch」させます。そして重要なのが「abort」を使っているところだそうです。

abort()は、強制的にアプリを終了させるコードです。むやみに使うとユーザーが戸惑ってしまうので多用してはいけませんが、こういう状況、データーベースをコピーすることができなかった場合、アプリを起動し続けることに意味のない状態に陥るようなことが分かっている場合、ログを残してアプリを終了させるのがデバックし易くなるということです。

 // 5
 let seededWALURL = bundle
    .URLForResource(self.seedName, withExtension: "sqlite-wal")!
 let walURL = self.applicationDocumentsDirectory
    .URLByAppendingPathComponent(self.seedName + ".sqlite-wal")
 do {
   try NSFileManager.defaultManager()
     .copyItemAtURL(seededWALURL, toURL: walURL)
 } catch {
   let nserror = error as NSError
   print("Error: (nserror.localizedDescription)")
   abort()
 }

「// 5」のステップも同じステップです。Xcodeに存在する3つのファイルをアプリのDocumentsディレクトリにコピーするステップでした。

さて、ここで初心者の疑問が生まれます。

  • SurfJournalDatabase.sqlite
  • SurfJournalDatabase.sqlite-shm
  • SurfJournalDatabase.sqlite-wal

この3つのファイルの意味は?「shm」「wal」???

明日はこのファイルに関して勉強します。