-
背景:
- 我們的APP只需要在用戶登錄的時候存儲一些關鍵的數據,數據量不大。其余數據在線請求就行,也沒有涉及大量的數據存儲,用Core Data 還挺方便的
-
當我要發布企業1.2版本的時候,發現因為用了CoreData進行數據的存儲,當我修改了里面的Model的時候。比如
CoreData里面的Model
-
當我添加或者修改一個字段或者是添加另外一個model的時候。我們會遇到兩個問題
- 1.運行到真機:會報錯,需要卸載APP后再運行重裝
-
2.發布版本后,你無法覆蓋安裝而且會出錯。安裝不了
**reason = "The model used to open the store is incompatible with the one used to create the store";**
-
而遇上這樣的問題肯定不行,用戶用不了你就掛了。所以我們要做版本的
數據遷移
- 但是這種情況沒有接觸過就只能Google了
- 參考地址:http://jamesonquave.com/blog/core-data-migrations-swift-tutorial/
-
Why Make Core Data Migrations?
However there is a problem. Core Data expects a consistent schema. Meaning that if we add or remove entities, attributes, or change their types, it will cause a conflict. This means that if you:1) Store some data inside of an app using a set schema. For example a Model named LogItem with a title(String) attribute.2) Change any of the schema. For example add a new full title attribute to become ‘fullTitle’.3) Run the app again
There will be a conflict, and the app will do a hard crash. This includes anyone who has downloaded your app from the app store! Not only that, if you change the text attribute, and you don’t perform any kind of migration, you will be risking losing user’s data. If you want people to uninstall your app, this is a fantastic way to make that happen.- 也就是我們上面遇上的問題:當你在swift中使用了CoreData,CoreData是需要一個始終如一的模式。如果你
修改了
,添加
或者移除
了任何一個實體
,屬性
或者修改了類型
。就會造成沖突
。就會導致運行
的時候你的APP崩潰
,或者別人在AppStore上下載你的APP后直接崩潰閃退,這是很嚴重的問題,丟失用戶可能是致命問題
- 也就是我們上面遇上的問題:當你在swift中使用了CoreData,CoreData是需要一個始終如一的模式。如果你
- 創建一個
遷移Migration
--Create A Migration- 沒創建遷移前Xcode會在AppDelegate中為我們自動創建下面的代碼。但是Xcode并沒有給出任何的
可選的遷移
。但是它有一個persistentStoreCoordinator
。它是專門負責遷移的發生。我們只需要關注options
。它是一個字典
,是一個遷移字典Migrations Options
- NSMigratePersistentStoresAutomaticallyOption sounds pretty nice. Automatic migration? Sign me up!
- NSInferMappingModelAutomaticallyOption will create the mapping model, while
- NSMigratePersistentStoresAutomaticallyOption will perform the migration.
- 沒創建遷移前Xcode會在AppDelegate中為我們自動創建下面的代碼。但是Xcode并沒有給出任何的
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
- 所以我們添加
let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions, error: &error) == nil {
- 創建遷移后是:
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
do {
let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
return coordinator
}()
- 也就是說,我們添加了:
let mOptions = [NSMigratePersistentStoresAutomaticallyOption: true,
NSInferMappingModelAutomaticallyOption: true]
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: mOptions)
這樣基礎的操作,是讓我們的Core Data去嘗試讓我們的Models在不同的版本之間自動合并以及映射
但是這樣還是不夠,我們還需要接下來的操作
添加一個Model版本--Add a Model Version
先要選上你的Core Data model,然后在工程的導航欄部分-->Editor-->Add Model Version(不選上,不會出現這個)
Add Model Version
Model Virsion
- 名字可以隨便起,但是建議最好叫xxxV2/3/...便于區分,因為你每遷移或者增加Model一次就產生了一次新的Model Schema.每次都會變的哦
- 然后我們就要Model Virsion2成為我們的可用的Model.選中Core Data model。然后:
ModelV2成為最新的可用的Model
對應Model文件中修改一下
這樣你就可以在MedelV2中修改你想修改的了,APP運行和發布后也就不會出錯了
-
重要的幾點:
- 1.設置好options
- 2.添加新的Model Virsion
- 3.選好新的Model Virsion
-
猜測的幾點
- 1.每次大的修改Model都要添加新的Model Virsion.版本不停往上
- 2.修改哪怕是退回去的時候,也最好是新建一個新的Model Virsion,刪除不想要的
- 3.有些還需要我去繼續驗證
蘋果產品對應架構
- 在項目中遇上了一個Swift中的一個坑:當APP發版后,有用戶發現他的iPhone5和5c裝上APP點擊登錄后直接崩潰閃退。其余的手機沒有問題。首先我以為是我們SDK支持的架構不支持ARMv7s,但是問清楚后發現是支持4s往上的。所以問題肯定出現在自己的程序中。查看崩潰日志(查看崩潰日志的工具Log Guru:http://club.fir.im/topic/54daf35374c4c85e73e4aaba)。
發現是自己有一個必須用到的參數id的問題
曾經我的id一直是Int64
- 這里的問題是:Swift是強語言,類型要求十分嚴格。我在Core Data里用了一個Integer64,然后Swift代碼里面寫的是Int。最后導致程序不能安裝(iPhone5和5c的CPU是32位的,所以要用Int32向上兼容。這里就用到了上面數據的遷移將它改成Int32,也不會出問題了)如果是已經上架AppStore的話,5和5c用戶就等下一個版本吧。。。我也就分分鐘去財務了