Swiftで遊ぼう! - 602 - Multiple Managed Object Contextsチュートリアル 7
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- Swift2.1 & Xcode7.1対応の日本語版アップルチュートリアル!
- Table View実装チュートリアルをXcode7.2.1で解説
- Core Data シンプルチュートリアル
- 私の本業、オフィシャルなブログ-> Life-LOG
下記のチュートリアルを取り組んでいますがチュートリアルで説明されていないNSFileManagerクラスを使ったファイル操作の勉強をしています。
昨日のdefaultManagerを使用する理由がまだはっきりしていませんが先に進みます。
NSFileManagerクラスはファイル操作、NSBundleクラスは存在するファイルの検索操作、のように考えていいかもしれません。この2つのクラスを使いこなして、アプリで管理するファイルを自由自在に扱えるようにします。
数日前の「チュートリアル4」でCoreDataStack.swiftのコードを載せましたが、その中にある1つの遅延格納型プロパティのNSPersistentSotoreCordinatorクラスの「psc」のみ注目します。
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 }()
重要なことを思い出す必要があります。「Swiftで遊ぼう! - 543 - Core Data シンプルチュートリアル - Swiftで遊ぼう! on Hatena」ここのチュートリアルに説明していますが、プロジェクト作成時に「Use Core Data」のチェックボックスを入れた場合、CoreDataStackはAppDelegateファイル上で初期化が生じるため、自前でCoreDataStackの初期化コードは要らないはずです。しかし、このスタータープロジェクトのAppDelegate.swiftファイルを見ると、CoreDataStackの初期化ステップがありません! という訳で、「Swiftで遊ぼう! - 530 - Core Data - Swiftで遊ぼう! on Hatena」で説明しているように、CoreDataStackクラスを用意しないといけません。私は一瞬勘違いしそうになりました。初心者の皆さん、注意が必要です。
定数「url」をもう一度注目します。
let url = self.applicationDocumentsDirectory .URLByAppendingPathComponent(self.seedName + ".sqlite")
「applicationDoucumentsDirectory」はDocumentsディレクトリの位置情報を保持する「NSURL」クラスのオブジェクトで、それが持つメソッド「URLByAppendingPathComponent()」を使って、ファイルのディレクトリ情報を「NSURL」クラスオブジェクトとして持たせています。
これが「//2」の「copyItemAtURL()」メソッドで指定されているコピー先です。このメソッドはerrorを投げる(thorws)が組み込まれているので、使用する場合「try」が必要になり、url指定先に既にファイルが存在しているとエラーになります。何もファイルが存在していなければ、メソッドは成功するので、「didCopyDatabase」に「true」が指定されます。
もう少し、この「copyItemAtURL()」メソッドを考えます。このコピー元のNSURLデータの「seededDatabaseURL」がどこから持ってくるのか理解している必要があります。「SurfJournalDatabase.sqlite」というファイルのNSURLオブジェクト情報は、NSFileManagerクラスメソッドではなく、NSBundleクラスメソッドを使って習得しています。
Xcodeに組み込んでいる「SurfJournalDatabase.sqlite」はNSBundleクラスを使ってアプリに取りこみます。
1度起動したアプリに存在する「SurfJournalDatabase.sqlite」はNSFileManagerを使って操作します。
やっと理解できました。