Comment restaurer l'utilisateur dans un emplacement de forage vers le bas la structure UITableViewController?

StackOverflow https://stackoverflow.com/questions/2203393

Question

J'ai un modèle CoreData qui contient des niveaux qui peuvent encore contenir childLevels.

Je représente chaque niveau avec une liste de tous les UITableViewController childLevels. Lorsqu'un utilisateur appuie sur une rangée, une nouvelle UITableViewController est poussé sur la navigationController. Pas de problème ici.

Comment pourrais-je aller sur le stockage de l'emplacement de l'utilisateur au sein de cette structure de la table. Y at-il une meilleure pratique pour ce faire? Je n'ai pas de problème à faire cela si la profondeur de la structure était connue, mais en quelque sorte perplexe comment aborder cela avec une profondeur indéfinie.

Dois-je stocker le NSIndexPath exploité par l'utilisateur dans un tableau et écrire sur le disque?

Était-ce utile?

La solution 2

Au lieu d'utiliser les NSIndexPaths taraudés par l'utilisateur que je suis allé avec les NSManagedObjects sous-jacentes qui est beaucoup plus sûr (en nombre de cas ou le tri des objets changent) et plus rapide (parce que je ne ai pas besoin du tout fetchRequest et ou vue).

Je le sous-classé UINavigationController et fait ce qui suit.

Lorsque vous appuyez sur une nouvelle TableViewController pour un niveau (stocké dans parentLevel) Je joins ce à un tableau dans UserDefaults:

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
   [super pushViewController:viewController animated:animated];

   if([viewController isKindOfClass:[LevelTableViewController class]]){
       NSMutableArray *array = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:LevelTablesPersistentKey]];
       NSManagedObject *obj = [(LevelTableViewController*)viewController parentLevel];

       if(obj!=nil){
         [array addObject:[[obj objectID].URIRepresentation absoluteString]];
       } 

       [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:array] objectForKey:LevelTablesPersistentKey];

   }
}

Quand je pop un viewController je supprimer simplement la dernière entrée de ce tableau:

- (UIViewController *) popViewControllerAnimated:(BOOL)animated{
  UIViewController *vc = [super popViewControllerAnimated:animated];
  // remove last object
  if([vc isKindOfClass:[LevelTableViewController class]]){
     NSMutableArray *array = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:LevelTablesPersistentKey]];
     [array removeLastObject];
     [[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithArray:array] objectForKey:LevelTablesPersistentKey];
  }

  return vc;
}

Je peux alors utiliser ce tableau lors de l'initialisation du NavigationController lorsque l'application est ensuite commencé à reconstruire l'arbre:

- (LevelNavigationController*) initWithRootViewController:(LevelTableViewController*)vc {
if(self = [super initWithRootViewController:vc]){
    // Recreate structure from UserDefaults
    NSArray *array = [NSArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:LevelTablesPersistentKey]];
    [[NSUserDefaults standardUserDefaults] setObject:nil forKey:LevelTablesPersistentKey]; // set the array to nil -> will be rebuild when pushing viewcontrollers onto navigation stack

    NSPersistentStoreCoordinator *persistentStoreCoordinator = ...; // pointer to coordinator 
            NSManagedObjectContext * managedObjectContext = ...; // pointer to your context
    for (NSString *objId in array) {
        NSManagedObjectID *mobjId=[persistentStoreCoordinator managedObjectIDForURIRepresentation:[NSURL URLWithString:objId]];
        if(mobjId!=nil){

            NSManagedObject *obj = nil;
            NSError **err = nil;
            obj = [managedObjectContext objectWithID:mobjId];

            if(err==nil && obj){
                if([obj.entity.name isEqualToString:@"Level"]){
                    // push level

                    LevelTableViewController *nextLevel = [[LevelTableViewController alloc] initWithStyle:UITableViewStylePlain];
                    nextLevel.parentLevel = (Level*)obj;
                    [self pushViewController:nextLevel animated:NO];
                    [nextLevel release];
                } 
            } 
        }
    }

}

return self;

}

Autres conseils

L'utilisation d'un NSIndexPath pour votre état et sauvegarde / restauration pour la persistance est logique pour moi.

Aussi votre approche - d'utiliser un NSArray stocké sous forme d'une liste de propriétés (plist) -. Devrait être assez simple

Je suis presque prêt à commencer à faire cela pour mon propre application et voici le plan. Chaque fois qu'un UIViewController charge une nouvelle vue, il va créer une valeur dans les NSUserDefaults qui donne des informations sur cette nouvelle vue (où il a été ouvert à partir, les données qu'il est peuplé avec, etc.). Lorsque le sous-vue renvoie le contrôleur de vue efface cette valeur. Lorsque le UIViewController a sa charge initiale, il vérifie les paramètres par défaut pour voir si elle précédemment stockée une valeur, le cas échéant, il prend les mesures appropriées pour recharger que sous-vue. Le processus se poursuit dans la chaîne de navigation.

La raison pour laquelle je l'ai fait au lieu d'un NSIndexPath est parce que, en plus de la hiérarchie de la vue principale, j'ai un tas de vues auxiliaires (ajouter, supprimer, modifier, etc.). Non seulement je besoin d'enregistrer l'ouverture de ces vues qui existent en dehors de la navigation principale, mais ils ont beaucoup de détails de l'Etat dont ils ont besoin pour sauver trop (options sélectionnées, texte partiellement saisi, etc.)

Je reviendrai ici et ce downvote si elle se révèle être un plan de merde.

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