2013年6月18日 星期二

Core Data - Migration

這裡有非常詳細的教學, 不過英文嘛, 我自己也看得很苦手

說是輕量搬移, 我也只會這樣整合
文章提到另外兩種manual, and custom code我也不會
寫越多的code越頭大

提一下文章講到的重點

假設已經如教學文章所說的, 建好一個Master-Detail Project
並且已經在右上的加號按了幾下新增了幾筆時間資料

現在可以先看新增好資料的Database, 以及實機呈現樣子以及Model設計
可以看到模擬器同Database有相同的5筆資料, 而model則是一個Date timeStamp欄位

接下來開始整合
首先, 去AppDelegate, 在以下方法中
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
其實裡面被註解的內容就有提到如何做整合
/*
         * Performing automatic lightweight migration by passing the following dictionary as the options parameter:
         @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
         
         Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
         */

把這一行
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
改為
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES} error:&error]) {
這樣程式要修改部分就完成了


接著去Model, 原本的model設計如上圖, 只有一個Date timeStamp
確定已經選取到PassingThoughts.xcdatamodeled, 接著 Editor -> Add Model Version...
第二版的model名稱就照預設給PassingThoughts 2就可以了
Based on model就看你要從哪一版的model去做修改
Finish之後可以看到原本的model變成這樣
接着還是點選着原本的root model檔案, 然後去inspector把current model修改為PassingThoughts 2
可以看到在project navigator中, model的勾選變成 PassingThoughts 2


繼續照個教學走
在新的PassingThoughts 2中, 原本的timeStamp如果沒有要更改欄位名稱, 那保持原樣即可
但如果要更改欄位名稱, 例如說改成when, 那直接對著timeStamp點兩下名稱改為when即可
然後在Renaming ID把舊有名稱timeStamp打上去

之後其他attribute設計就跟一般情況一樣, 可以設計個String what, String where上去


忘記講個很重要的事, 因為我把原本欄位名稱timaStamp改為when
所以要去MasterViewController.m中, 把所有原本timeStamp都取代為when
如果沒有動到裡面的檔案的話一共有三處要修改


最後再來重新Run Porject, 完成如下圖
可以看到五筆舊有的timeStamp內容都一樣, 且欄位名稱變成when
並且新增了兩個欄位, what及where


2013/6/19 補充個簡單東西, 實際上用不太到
//若Destination.sqlite不存在才會進入, 也就是第一次開啟App, Destination.sqlite尚未建立
    if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) {
        NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"CoreDataTutorial2" ofType:@"sqlite"]];

        NSError* err = nil;
        
        if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&err]) {
            NSLog(@"Oops, could copy preloaded data");
        }
    }
這是如果一開始就有已經設計好的DB(Source.sqlite要拖到porject內), 可以將DB內的內容copy到要從model建立新的DB(Destination.sqlite)
來源DB欄位要跟model設計的一樣, 不可多不可少,不然會無法把內容copy進去
放置位置在下列程式碼之後
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Destination.sqlite"];

2013/6/21 再補充 有關上述19號講的東西
試了一下其實是可以將欄位設計成跟原本要copy進去的不一樣的
但是這樣model就要設計成兩個, 就跟這篇文章主旨講的一樣
原始的model的attribute使用跟要copy進去的DB欄位一樣
而model 2的attribute則一樣隨自己再設計, 要改欄位名稱的話一樣記得renaming ID要打上原本的attribute

沒有留言:

張貼留言