Подтвердить что ты не робот

Сохранение состояния iOS и просмотр контейнеров

У меня есть контроллер представления в раскадровке, использующей представление контейнера. Оба имеют идентификаторы восстановления. Родитель сохраняется и восстанавливается просто отлично. Ребенок, однако, нет. Ни один из -encodeRestorableStateWithCoder: или -decodeRestorableStateWithCoder: не вызывается на контроллере дочернего представления.

Каков правильный способ сохранения дочерних контроллеров представления, созданных с контейнером представления? Я могу сохранить контроллер дочернего представления в родителях -encodeRestorableStateWithCoder:, что приведет к его сохранению, но у меня нет возможности использовать его во время восстановления.

4b9b3361

Ответ 1

Контроллер просмотра контейнера "не автоматически сохраняет ссылки на какие-либо содержащиеся контроллеры дочерних представлений. Если вы реализуете настраиваемый контроллер представления контейнеров, вы должны сами закодировать объекты контроллера дочернего представления, если хотите, чтобы они сохранялись".

Существуют простые правила, которые я нашел:

1. Контроллер представления данных (дочерний) должен быть уже создан и добавлен в контроллер родительского представления при сохранении состояния. Таким образом, не нужно ничего делать, если вы используете раскадровку, иначе вам придется создать экземпляр контроллера детского просмотра и добавить его вручную:

-(void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"Did load");
    MyChildViewController *childViewController = [MyChildViewController new];
    [self addChildViewController:childViewController];
    [childViewController didMoveToParentViewController:self];
    self.childVC = childViewController;
}

Вы можете добавить дочерний вид в -viewDidLoad или позже. Используйте self.childVC.view.frame = [self frameForChildController]; [self.view addSubview:self.childVC.view]; для этого.

2. Вам не нужно сохранять контроллер дочернего представления в родительском -encodeRestorableStateWithCoder:, но вы должны закодировать ссылку на этот объект, используя -encodeObject:forKey:. Если у вас есть ссылка, вы можете сделать это следующим образом:

-(void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    NSLog(@"Encode");
    UIViewController *childViewController = self.childVC;
    [coder encodeObject:childViewController forKey:@"ChildVC"];
    [super encodeRestorableStateWithCoder:coder];
}

см. fooobar.com/questions/36724/..., чтобы получить ссылку на дочерний VC, если вы используете Storyboard. Или вы можете написать что-то простое:

-(void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
    NSLog(@"Encode");
    UIViewController *childViewController = [self.childViewControllers objectAtIndex:0]; //[self.childViewControllers lastObject];
    [coder encodeObject:childViewController forKey:@"ChildVC"];
    [super encodeRestorableStateWithCoder:coder];
}

3. Встроенный (дочерний) контроллер представления должен быть уже создан и добавлен в контроллер родительского представления в процессе восстановления состояния. Итак, если вы сделали все в первом абзаце, здесь больше нечего делать.

4. "В этом случае мы не декодируем контроллер дочернего представления. Мы могли бы, но на самом деле нам это не нужно. Объект MyChildViewController будет восстанавливать свое собственное состояние. Мы только кодировали эту ссылку, чтобы получить время выполнения, чтобы перейти по цепочке к экземпляру MyChildViewController и сохранить и восстановить его".

-(void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
    NSLog(@"Decode");
    [super decodeRestorableStateWithCoder:coder];
}

Эта книга помогает мне понять сохранение состояния с видами контейнера. Также посмотреть для хорошего примера для этой книги

Ответ 2

Я думаю, что ответ находится в documentation Говорят:

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

Итак, вы можете сделать что-то вроде этого:

-(void)encodeRestorableStateWithCoder:(NSCoder *)coder {
    [super encodeRestorableStateWithCoder:coder];
    [self.myChildViewController encodeRestorableStateWithCoder:coder];
}

-(void)decodeRestorableStateWithCoder:(NSCoder *)coder {
    [super decodeRestorableStateWithCoder:coder];
    [self.myChildViewController decodeRestorableStateWithCoder:coder];
}

А в MyChildViewController не вызывайте super:)