2011-10-03 3 views
3

Je reçois ce message d'erreur (et accident ultérieure) organiseur Xcode que je soupçonne est lié à une migration des données de base qui prend trop de temps pour terminer:iOS noyau temps de migration de données sur

4 octobre 09: 51:14 SpringBoard inconnu [30]: appName n'a pas réussi à lancer dans le temps

Cette migration des œuvres trouvent dans le simulateur, même quand j'insérer des retards artificiels (à l'aide de sommeil (100), par exemple).

Ce n'est que lorsque j'essaie de tester sur un iPhone 4 ou iPod 4ème génération que je reçois ce message d'erreur de timeout.

Si une migration n'est pas nécessaire, en fournissant la version de base de données sqlite3 correcte pendant la génération, il n'y a pas de plantage.

Voici ce qui se passe, dans le code:

Dans le délégué de l'application:

- (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; 
}` 

Le persistentStoreCoordinator est une méthode assez longue, heureuse de fournir si nécessaire. Il migre deux bases de données, d'environ 500 Ko chacune. Le premier réussit toujours mais le second échoue toujours (sur l'appareil), mais les deux réussissent toujours dans le simulateur. Les propriétésTableViewController présentent une vue tabulaire avec les données issues de la base de données migrée. La migration doit donc avoir lieu avant que la propriété propertiesTableViewController ne s'affiche.

J'ai aussi essayé d'essayer de déclencher la migration à l'intérieur du propertiesTableViewController (dans la méthode viewDidLoad) en utilisant:

  • [NSThread detachNewThreadSelector: @selector (getMOC) toTarget: auto withObject: nil] -> se bloque car la vue de la table ne peut pas accéder au contexte de l'objet géré qui n'est pas prêt car la migration est toujours en cours.
  • [self performSelectorOnMainThread: @selecteur (getMOC) avecObjet: nil waitUntilDone: YES]; -> Crashes avec la même erreur de délai d'attente

La méthode getMOC est la suivante:

-(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]; 
} 

Répondre

6

Je pense que vous devez reporter montrant le contrôleur de navigation jusqu'à ce que la migration terminée, soit vous devrez peut-être afficher un "contrôleur de progression".

Le plus simple est probablement afficher le contrôleur de progression au démarrage:

- (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 
    ... 
} 

Une option légèrement mieux est d'abord essayer de charger les magasins persistants avec NSMigratePersistentStoresAutomaticallyOption désactivé. Si cela échoue, affichez la progression VC et réessayez en arrière-plan; Si cela réussit, vous pouvez afficher le VC normal directement (dans le code ci-dessus, vous pouvez simplement appeler -persistentStoreLoaded directement à partir de -application:didFinishLaunchingWithOptions:).

+0

Merci, cela m'a aidé. J'ai implémenté quelque chose de similaire à vos premières suggestions, seulement que j'ai testé l'idée en mettant les méthodes Core Data dans le contrôleur de progression et en déclenchant la migration via un bouton (j'automatiserai ceci, mais je veux d'abord faire un test de santé). – futureshocked

+0

Cela se passe-t-il dans un fil d'arrière-plan?Si ce n'est pas le cas, cela peut sembler fonctionner mais échouer si l'utilisateur place votre application à la moitié de la migration. –

Questions connexes