読者です 読者をやめる 読者になる 読者になる

Swiftで遊ぼう! on Hatena

あしたさぬきblogでやってた初心者オヤジのiOSプログラミング奮闘記がHatenaに来ました

Swiftで遊ぼう! - 606 - Multiple Managed Object Contextsチュートリアル 10

PersistentManagerCoordinator初期化最後のステップの説明に入ります。

www.raywenderlich.com

アプリを最初に立ち上げた時にDocumentsディレクトリに何もなければ、「didCopyDatabase」が「true」になり、Xcodeプロジェクト内の3つのファイルをコピーしてから、Xcodeのコンソールに"Seeded Core Data"が表示されます。

そして、「//6」と「//7」ののコードを見ます。

// 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

定数「coordinator」はクロージャー内で宣言しているNSPersistentStoreCoordinator型のインスタンスで、実際はreturnされるlazyタイプの変数「psc」のことです。クロージャー内の最初に宣言されているコードをみます。

let coordinator = NSPersistentStoreCoordinator(
      managedObjectModel: self.managedObjectModel)

NSPersistentStoreCoordinatorクラスの初期化には、ManagedObjectModelクラスの情報が要ります。これはデータベースのシェーマにあたり保存形式を決定するために当然と言えば当然です。このManagedObjectModelに「self.」が付いているというのも、プロパティに「Lazy」を付けなければいけない理由の1つになります。

次は、CoreDataStackクラスの重要プロパティである「ManagedObjectModel」型プロパティ宣言をみてみます。

lazy var managedObjectModel: NSManagedObjectModel = {
 let modelURL = NSBundle.mainBundle()
  .URLForResource(self.modelName,
    withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()

managedObjectModelもXcodeプロジェクトのファイルから取り込む必要があります。NSBundleクラスを使って、Xcodeプロジェクトで設定したManagedObjectModelをNSURLクラスにします。以前にも出てきましたがURLForRrsourecメソッド使っています。String型のファイル名を指定すればNSURLオブジェクトが習得できます。

f:id:yataiblue:20160304095527j:plain

また疑問が生まれました。このURLForResource()メソッドの引数「withExtension」ですが、"momd"を与えています。

ここでパラメータのextensionで疑問があります。Documentation and API Referenceには以下の説明があります。

If extension is an empty string or nil, the extension is assumed not to exist and the file URL is the first file encountered that exactly matches name.

extensionの指定が空かnilならnameと一致するファイルのNSURLオブジェクトを作成しますが、ここで「momd」が指定されています。Xcodeプロジェクトにあるファイルは「SurfJournalModel.xcdatamodeld」なんで、一致しないような気がしますが、「momd」を「xcdatamodeld」に変更するとランタイムエラーになります。どうしてでしょうか?

なぜかわかりませんが、これでmanagedObjectModelオブジェクトができます。

そして、定数coordinatorはこのオブジェクトを使ってプロパティ化されます。

もう一度「//6」のコードを見ます。

try coordinator.addPersistentStoreWithType(
  NSSQLiteStoreType, configuration: nil, URL: url, options: nil)

NSPersistentStoreCoordinatorクラスのメソッド、addPersistentStoreWithTypeが出てきました。そのまま読むと、Documentsディレクトリにある「SurfJournalDatabase.sqlite」をNSSQLiteStoreTypeにして保存する作業ですね。

まあこれでなんとかCoreDataStackの起動ができました。