Question

Résolution: Tout en essayant de recréer ce bogue dans un nouveau projet à soumettre à Apple, j'ai découvert qu'il est spécifique à iPhone OS 2.1 et la compilation pour la version 2.2 corrige le problème. Stephen, merci pour votre aide. Je vais accepter votre réponse car cela aurait fonctionné si le bogue existait encore ou si je ne souhaitais pas compiler pour la version 2.2.

J'ai une application qui modifie radicalement son schéma de base de données de manière à ce que je transforme les enregistrements de style ancien en codes de style nouveau. Étant donné que les utilisateurs peuvent stocker beaucoup de données dans cette application, j'essaie d'afficher un contrôleur de vue modale avec une barre de progression pendant qu'il transfère les données (c'est-à-dire en tant que première chose que l'utilisateur voit). Le viewDidAppear: de ce contrôleur de vue commence une transaction de base de données puis un thread d'arrière-plan pour effectuer le portage réel, qui utilise occasionnellement performSelectorInMainThread: withObject: waitUntilDone: pour indiquer le thread d'avant-plan à mettre à jour la barre de progression.

Le problème est que viewDidAppear: est appelé deux fois. Je l’ai remarqué car cela "lance une transaction". l'étape échoue avec un " base de données occupée " message, mais la définition d'un point d'arrêt révèle qu'il est en fait appelé deux fois une fois par - [UIViewController viewDidMoveToWindow: shouldAppearOrDisappear:] et de nouveau par - [UIViewController modalPresentTransitionDidComplete] . . Ces noms semblent être des méthodes privées UIViewController, alors je suppose que c'est soit un bogue du framework, soit je fais quelque chose que UIKit ne s'attend pas à ce que je fasse.

Deux extraits de code pertinents (certains codes non pertinents ont été résumés):

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    (register some default settings in NSUserDefaults)

    // doing this early because trying to present a modal view controller 
    // before the view controller is visible seems to break it
    [window addSubview:[self.navigationController view]];

    // this is the method that may present the modal view
    [self.databaseController loadDatabaseWithViewController:self.navigationController];

    if(!self.databaseController.willUpgrade) {
        [self restoreNavigationControllerState];
    }
}

Et de ma classe DatabaseController:

- (void)loadDatabaseWithViewController:(UIViewController*)viewController {
    (open the new database)

    (compute the path the old database would live at if it existed)

    if([[NSFileManager defaultManager] fileExistsAtPath:oldDBPath]) {
        (open the old database)

        [viewController presentModalViewController:self animated:NO];
    }
}

Alors, y a-t-il quelque chose que je déconne ici ou dois-je déposer un rapport de bogue avec Apple?

Était-ce utile?

La solution

J'ai aussi vu cela dans mon application. Je ne l'ai jamais entièrement confirmé, mais je pense que c'est ce qui se passe:

  1. Charger la vue racine
  2. Charger la vue modale
  3. La vue envoyée par le système d'exploitation apparaît dans la notification à l'étape 1
  4. Le contrôleur de vue actuel , qui dans ce cas se trouve être votre classe DatabaseController, le récupère
  5. Le système d’exploitation envoie la vue qui apparaît une notification pour la vue modale
  6. Le contrôleur de vue actuel obtient la notification. Dans ce cas, c'est exactement le même contrôleur que la dernière fois

Dans mon cas, je viens de réinitialiser ce qui s'est passé lors du premier appel à viewDidAppear: .

Dans votre cas, deux options vous viennent à l’esprit: une variable statique pour savoir si vous avez déjà commencé la mise à niveau; ou regardez le paramètre UIView * passé avant de commencer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top