2011-10-03 161 views
3

我得到在Xcode的組織者,我懷疑是關係到核心數據遷移是需要很長時間才能完成此錯誤消息(以及隨後的崩潰):的iOS核心數據遷移超時

09年10月4日: 51:14未知SpringBoard [30]:appName無法及時啓動

即使插入虛假延遲(例如使用sleep(100)),此遷移仍可在模擬器中找到。

只有當我嘗試在iPhone 4或iPod第四代上測試時,我纔會收到此超時錯誤消息。

如果不需要遷移,通過在構建過程中提供正確的sqlite3數據庫版本,不會出現崩潰。

這裏是發生了什麼,在代碼:

在應用程序委託:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  

    PropertiesTableViewController *propertiesTableViewController = 
      [[PropertiesTableViewController alloc] initWithManagedObjectContext:self.managedObjectContext]; 

    UINavigationController *newNavController = 
         [[UINavigationController alloc] 
         initWithRootViewController:propertiesTableViewController]; 


    [propertiesTableViewController release]; 
    [window addSubview:newNavController.view]; 


    NSLog(@"UUID: %@", [[UIDevice currentDevice] uniqueIdentifier]); 

    [window makeKeyAndVisible]; 

    return YES; 
} 


- (NSManagedObjectContext *) managedObjectContext { 

    if (managedObjectContext != nil) { 
     return managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 
     managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [managedObjectContext setPersistentStoreCoordinator: coordinator]; 
    } 
    return managedObjectContext; 
}` 

的persistentStoreCoordinator是一個相當長的方法,高興,如果需要提供它。它遷移兩個數據庫,每個數據庫大約500kBytes。第一個總是成功,但第二個總是失敗(在設備上),但是兩個總是在模擬器中成功。 propertiesTableViewController使用從遷移數據庫獲取的數據顯示錶視圖,因此必須在propertiesTableViewController進入查看之前進行遷移。

我還試圖嘗試使用觸發從propertiesTableViewController內的遷移(在viewDidLoad方法):

  • [NSThread detachNewThreadSelector:@selector(getMOC)toTarget:自withObject:無] - >因爲遷移仍在進行中,因此表視圖無法訪問未準備好的託管對象上下文。
  • [self performSelectorOnMainThread:@selector(getMOC)withObject:nil waitUntilDone:YES]; - >用相同的超時錯誤

的getMOC方法崩潰是這樣的:

-(void)getMOC 
{ 
    NSAutoreleasePool *autoreleasePoolProperty = [[NSAutoreleasePool alloc] init]; 
    NSLog(@"getting appDelegate from PropertiesTableViewController"); 

    iNspectorAppDelegate *appDelegate = (iNspectorAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    NSLog(@"getting managedObjectContext from PropertiesTableViewController");  
    self.managedObjectContext = [appDelegate managedObjectContext]; 
    NSLog(@"got managedObjectContext from PropertiesTableViewController"); 
    [autoreleasePoolProperty release]; 
    [self performSelectorOnMainThread:@selector(finishedGettingPropertyData) withObject:nil waitUntilDone:NO]; 
} 

回答

6

我認爲你需要推遲顯示導航控制器,直到遷移完成,也就是說,你可能需要顯示「進度控制器」。

最簡單的方法可能是在啓動時顯示進度控制:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions 
{ 
    ... 
    [window addSubview:progressController.view]; 
    [window makeKeyAndVisible]; 
    [self performSelectorInBackground:@selector(loadPersistentStore) withObject:nil]; 
} 

-(void)loadPersistentStore 
{ 
    [self persistentStoreCoordinator]; 
    [self performSelectorOnMainThread:@selector(persistentStoreLoaded) withObject:nil waitUntilDone:NO];` 
} 

-(void)persistentStoreLoaded 
{ 
    [progressController.view removeFromSuperview]; 
    self.progressController = nil; 

    // Load the normal VC here 
    ... 
} 

一個稍微好一點的選擇是第一次嘗試與NSMigratePersistentStoresAutomaticallyOption裝載持久性存儲關閉。如果失敗,則顯示進度VC並在後臺重試;如果成功,則可以直接顯示正常VC(在上面的代碼中,您可以直接從-application:didFinishLaunchingWithOptions:調用-persistentStoreLoaded)。

+0

謝謝,這有幫助。我實現了類似於你的第一個建議的東西,只是我通過將Core Data方法放入進度控制器並通過按鈕觸發遷移來測試這個想法(我將自動執行此操作,但希望首先進行完整性測試)。 – futureshocked

+0

它發生在後臺線程中嗎?如果沒有,它可能會工作,但仍然失敗,如果用戶背景你的應用程序通過遷移的一半。 –