我們的應用需要核心數據輕量級遷移,因爲我們已向實體添加了一些屬性。核心數據輕量級遷移不會在發佈時遇難
在TestFlight上發佈更新給我們的beta測試者後,我們從其中一些人那裏報告說應用程序在啓動時崩潰了。得到崩潰日誌後,我們意識到跳板看門狗正在殺死該應用程序,因爲遷移時間過長。
在網上淘資源後,似乎可以通過首先檢查是否需要遷移,不接觸核心數據堆棧並選擇在另一個視圖控制器中執行遷移來卸載application:didFinishLaunchingWithOptions:
之外的遷移。這裏是我想要做的事:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([[ZSSCoreDataManager sharedService] migrationRequired]) {
UpgradeDatabaseViewController *upgrade = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:@"UpgradeDatabaseViewController"];
self.window.rootViewController = upgrade;
}
return YES;
}
遷移測試:
- (BOOL)migrationRequired {
NSManagedObjectModel *mom = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
NSError *error = nil;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMergeTest.sqlite"];
// Determine if a migration is needed
NSDictionary *sourceMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:storeURL options:nil error:&error];
NSManagedObjectModel *destinationModel = [persistentStoreCoordinator managedObjectModel];
BOOL pscCompatibile = [destinationModel isConfiguration:nil compatibleWithStoreMetadata:sourceMetadata];
return !pscCompatibile;
}
UpgradeDatabaseViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"Starting migration");
// Start migration by accessing th epersistent container
[[ZSSCoreDataManager sharedService] persistentContainer];
NSLog(@"Ended migration");
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UINavigationController *nav = [self.storyboard instantiateViewControllerWithIdentifier:@"MainNav"];
window.rootViewController = nav;
}
持續容器:
- (NSPersistentContainer *)persistentContainer {
@synchronized (self) {
if (_persistentContainer != nil) {
return _persistentContainer;
}
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"Model"];
// Store description
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataMergeTest.sqlite"];
NSPersistentStoreDescription *description = [NSPersistentStoreDescription persistentStoreDescriptionWithURL:storeURL];
description.shouldInferMappingModelAutomatically = YES;
description.shouldMigrateStoreAutomatically = YES;
description.type = NSSQLiteStoreType;
_persistentContainer.persistentStoreDescriptions = @[description];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error){
if (error != nil) {
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
//abort();
}
}];
_persistentContainer.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy;
_persistentContainer.viewContext.undoManager = nil; // We don't need undo so set it to nil.
_persistentContainer.viewContext.shouldDeleteInaccessibleFaults = YES;
_persistentContainer.viewContext.automaticallyMergesChangesFromParent = YES;
}
return _persistentContainer;
}
可悲的是,這仍然沒有按似乎沒有解決問題因爲跳板仍然會殺死應用程序(當設備未插入並且調試器正在運行時)。
這裏有什麼我做錯了嗎?不管我們是否不啓動我們的數據庫,輕量級遷移是否發生在application:didFinishLaunchingWithOptions:
中?
在使用輕量級遷移時,甚至可以做我想做的事情嗎?
我已更新我的問題以顯示如何創建我的'NSPersistentContainer'。這就是我用來初始化我的Core Data堆棧,因爲我們的應用程序是iOS 10.您是否說我可以在後臺隊列上創建我的'NSPersistentContainer'對象? –
我能夠重現我的用戶擁有的崩潰。用戶向我提供了他們的.sqlite文件。自從我的設備連接到調試器並且看門狗進程沒有運行以來,我從未看到過崩潰。 –
@NicHubbard我的答案已經涵蓋了如何以及何時應該設置持久容器的細節。有沒有關於它的具體內容尚不清楚? –