Как восстановить местоположение пользователя в развернутой структуре UITableViewController? - PullRequest
1 голос
/ 05 февраля 2010

У меня есть модель CoreData, которая содержит уровни, которые могут снова содержать childLevels.

Я представляю каждый уровень с UITableViewController перечислением всех childLevels.Когда пользователь нажимает на строку, новый UITableViewController помещается на navigationController.Здесь нет проблем.

Как мне сохранить местоположение пользователя в этой структуре таблицы?Есть ли лучшая практика для этого?У меня нет проблем с этим, если глубина структуры была известна, но каким-то образом озадачил, как приблизиться к этому с неопределенной глубиной.

Должен ли я сохранить NSIndexPath, введенный пользователем, в массив и записать егона диск?

Ответы [ 3 ]

1 голос
/ 05 февраля 2010

Вместо того чтобы использовать NSIndexPaths, подключенные пользователем, я пошел с базовыми NSManagedObjects, которые намного безопаснее (в случае изменения числа или сортировки объектов) и быстрее (потому что мне не нужен весь fetchRequest и / или представление). 1001 *

Я вложил в подкласс UINavigationController и сделал следующее.

При добавлении нового TableViewController для уровня (хранится в parentLevel) я добавляю это к массиву в 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];

   }
}

Когда я запускаю viewController, я просто удаляю последнюю запись из этого массива:

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

Затем я могу использовать этот массив при инициализации NavigationController при следующем запуске приложения для перестройки дерева:

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

}
1 голос
/ 05 февраля 2010

Использование NSIndexPath для вашего состояния и сохранение / восстановление его для сохранения имеет смысл для меня.

Также ваш подход - использовать NSArray, хранящийся в виде списка свойств (plist) - должен быть довольно простым.

0 голосов
/ 05 февраля 2010

Я почти готов начать делать это для моего собственного приложения, и вот план. Каждый раз, когда UIViewController загружает новое представление, он создает в NSUserDefaults значение, которое предоставляет информацию об этом новом представлении (откуда оно было открыто, какие данные заполнены и т. Д.). Когда подпредставление возвращает, контроллер представления очищает это значение. Когда UIViewController имеет свою начальную загрузку, он проверяет значения по умолчанию, чтобы увидеть, сохранено ли ранее значение, если это так, он предпринимает соответствующее действие для перезагрузки этого подпредставления. Процесс продолжается вниз по цепочке навигации.

Причина, по которой я сделал это вместо NSIndexPath, заключается в том, что, помимо иерархии основного представления, у меня есть несколько вспомогательных представлений (добавление, удаление, редактирование и т. Д.). Мне нужно будет не только регистрировать открытие этих представлений, которые существуют за пределами основной навигации, но они также будут содержать множество сведений о состоянии, которые им также необходимо сохранить (выбранные параметры, частично введенный текст и т. Д.)

Я вернусь сюда и уменьшу это, если это окажется дерьмовым планом.

...