想了一會兒,我想出了一個解決方案,我很滿意。 exit(0)
選項需要考慮的一件事是,如果用戶需要一段時間解鎖設備,應用程序可能會不斷加載,退出和重新加載。而如果你只是阻止應用程序做了很多事情,它可能只需要加載一次,而且很可能會更有效率。所以我決定試試我的選項3,看看它真的有多混亂。結果比我想象的要簡單。
首先,我將BOOL setupComplete
屬性添加到我的應用程序委託。這給了我一個簡單的方法來檢查應用程序是否在各個點完全啓動。然後在application:didFinishLaunchingWithOptions:
我嘗試初始化管理對象上下文,然後做這樣的事情:
NSManagedObjectContext *moc = [self managedObjectContext];
if (moc) {
self.setupComplete = YES;
[self setupWithManagedObjectContext:moc];
} else {
UIApplication *app = [UIApplication sharedApplication];
if ([app applicationState] == UIApplicationStateBackground && ![app isProtectedDataAvailable]) {
[app beginIgnoringInteractionEvents];
} else [self presentErrorWithTitle:@"There was an error opening the database."];
}
setupWithManagedObjectContext:
僅僅是一個自定義的方法,這樣就完成設置。我不確定beginIgnoringInteractionEvents
是否有必要,但我補充說它是安全的。這樣,當應用程序被帶到前面時,我可以確定界面被凍結,直到安裝完成。如果渴望的用戶焦急地竊聽,它可能會避免崩潰。
然後在applicationProtectedDataDidBecomeAvailable:
我把這樣的事情:
if (!self.setupComplete) {
NSManagedObjectContext *moc = [self managedObjectContext];
if (moc) {
self.setupComplete = YES;
[self setupWithManagedObjectContext:moc];
UIApplication *app = [UIApplication sharedApplication];
if ([app isIgnoringInteractionEvents]) [app endIgnoringInteractionEvents];
} else [self presentErrorWithTitle:@"There was an error opening the database."];
}
這樣就完成了安裝和重新啓用接口。這是大部分工作,但您還需要檢查其他代碼,以確保在持久存儲可用之前沒有任何依賴於核心數據的調用。有一點需要注意的是,如果用戶從此後臺狀態啓動應用程序,applicationWillEnterForeground
和applicationDidBecomeActive
可能會在applicationProtectedDataDidBecomeAvailable
之前調用。因此,我在不同的地方添加了0以確保在準備就緒之前不會有任何運行。一旦數據庫被加載,我還有幾個需要刷新界面的地方。
爲了(部分)測試這個沒有很多開車過來的,我臨時修改application:didFinishLaunchingWithOptions:
不設置數據庫:
NSManagedObjectContext *moc = nil; // [self managedObjectContext];
if (moc) {
self.setupComplete = YES;
[self setupWithManagedObjectContext:moc];
} else {
UIApplication *app = [UIApplication sharedApplication];
// if ([app applicationState] == UIApplicationStateBackground && ![app isProtectedDataAvailable]) {
[app beginIgnoringInteractionEvents];
// } else [self presentErrorWithTitle:@"There was an error opening the database."];
}
然後我在applicationProtectedDataDidBecomeAvailable:
感動我的代碼到applicationWillEnterForeground:
。這樣我可以啓動應用程序,確保沒有意外發生,按主頁按鈕,再次打開應用程序,並確保一切正常。由於實際的代碼需要移動很長的距離並且每次等待五分鐘,這給了我一個很好的方式來估計發生的事情。
絆倒我的最後一件事是我的持續性店鋪協調員。一個典型的實現可能是這個樣子:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) return _persistentStoreCoordinator;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Test.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
return _persistentStoreCoordinator;
}
這是鬆散的基礎上蘋果的示例代碼,這並在你需要適當處理錯誤註釋解釋。我自己的代碼做的不僅僅是這一點,但有一件事我沒有考慮到,如果加載持久存儲時出錯,這將返回非零結果!這是讓我所有的其他代碼繼續進行,就好像它正常工作。即使persistentStoreCoordinator再次被調用,它也只會返回相同的協調器,而沒有有效的存儲區,而不是再次嘗試加載存儲區。有多種方法,你可以解決這個問題,但對我來說似乎是最好不要設置_persistentStoreCoordinator,除非它能夠添加商店:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator != nil) return _persistentStoreCoordinator;
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Test.sqlite"];
NSError *error = nil;
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if ([coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
_persistentStoreCoordinator = coordinator;
} else {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
return _persistentStoreCoordinator;
}
@robertspacer 不會_persistentStoreCoordinator是nil上這一行: 如果([_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType配置:無URL:storeURL選項:無誤差:&錯誤]){ – 2013-04-05 22:43:12
@GlenŤ是的,這應該一直是協調員的參考。固定。 – robotspacer 2013-04-08 23:59:48