Pergunta

Eu tenho um modelo CoreData que contém níveis que possam novamente contêm childLevels.

Eu represento cada nível com um UITableViewController listando todos childLevels. Quando um usuário toca uma linha um novo UITableViewController é colocado na navigationController. Nenhum problema aqui.

Como eu iria sobre como armazenar a localização do usuário dentro desta estrutura de tabela. Existe uma prática recomendada para fazer isso? Não tenho nenhum problema em fazer isso se a profundidade da estrutura era conhecida, mas de alguma forma intrigado como abordar isso com uma profundidade indefinida.

Devo armazenar o NSIndexPath aproveitado pelo usuário em uma matriz e escrevê-lo para o disco?

Foi útil?

Solução 2

Em vez de usar os NSIndexPaths aproveitado pelo usuário Fui com os NSManagedObjects subjacente que é muito mais seguro (em número de processo ou a classificação da mudança objetos) e mais rapidamente (porque eu não preciso de toda a fetchRequest e ou vista).

Eu subclasse o UINavigationController e fez o seguinte.

Ao empurrar um novo TableViewController para um nível (armazenado em parentLevel) I acrescentar este para uma matriz em 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];

   }
}

Quando eu estalar um viewController eu simplesmente remover a última entrada a partir desse array:

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

Posso, então, usar essa matriz ao inicializar o NavigationController quando o aplicativo é próxima começou a reconstruir a árvore:

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

}

Outras dicas

Usando um NSIndexPath para seu estado e salvar / restaurá-lo para a persistência faz sentido para mim.

Além disso a sua abordagem - para usar um NSArray armazenado como uma lista de propriedades (plist) -. Deve ser bastante simples

Eu estou quase pronto para começar a fazer isso para o meu próprio aplicativo e aqui está o plano. Cada vez que um UIViewController cargas uma nova visão que vai criar um valor nas NSUserDefaults que dá informações sobre essa nova visão (onde foi aberto a partir, os dados que é preenchida com, etc). Quando o subexibição retorna o controlador de vista limpa fora este valor. Quando o UIViewController tem a sua carga inicial ele verifica os padrões para ver se ele previamente armazenado um valor, em caso afirmativo, que leva a ação apropriada para recarregar que subexibição. O processo continua para baixo na cadeia de navegação.

A razão de eu ter feito isso em vez de um NSIndexPath é porque, além de a principal hierarquia vista, eu tenho um monte de vistas auxiliares (adicionar, remover, editar, etc.). Não só eu preciso para gravar a abertura dessas visões que existem fora da navegação principal, mas eles terão um monte de detalhes de estado que eles precisam para salvar também (opções selecionadas, texto parcialmente introduzido, etc.)

Eu vou voltar aqui e downvote isso se ele sair para ser um plano de merda.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top