2013-04-03 19 views
17

Mam kontroler widoku w scenopisie używającym widoku kontenera. Oba mają ustawione identyfikatory przywracania. Rodzic jest zapisywany i przywracany dobrze. Dziecko jednak nie jest. Na kontrolerze widoku podrzędnego nie są wywoływane -encodeRestorableStateWithCoder: ani -decodeRestorableStateWithCoder:.Zachowanie stanu i kontenera stanu iOS

Jaki jest poprawny sposób zapisywania kontrolek widoku podrzędnego, które są tworzone za pomocą kontenera widoku? Można zapisać kontroler widoku podrzędnego w rodzicach -encodeRestorableStateWithCoder:, który spowoduje, że zostanie zapisany, ale nie mam sposobu na jego użycie podczas przywracania.

+0

Czy dodać dziecka do rodzica z addChildViewController: – jsd

+0

tak nazywasz didMoveToParentViewController: metodę po dodaniu kontrolera widoku dziecko do kontrolera widoku rodzica – HermioneGreen

+0

widok pojemnik powinien Robię to automatycznie. Otrzymuję odwołanie do niego od rodziców childViewControllers. –

Odpowiedz

-1

Myślę, że odpowiedź jest w documentation Mówi:.

"Klasa UIViewController zapisuje odniesienie do prezentowanego kontrolera widoku i serii ujęć (jeśli istnieje), który został użyty do utworzenia kontroler zobaczyc kontroler widoku prosi również o widoki w hierarchii widoku, aby zapisać wszelkie istotne informacje: Jednak ta klasa nie zapisuje automatycznie odwołań do żadnych zawartych kontrolerów widoku podrzędnego .Jeśli implementujesz niestandardowy kontroler widoku kontenera, musisz zakodować widok podrzędny kontroler obiektów siebie, jeśli chcesz je zachować. "

Więc można zrobić coś takiego:

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

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

I MyChildViewController nie nazywają Super :)

+0

Moje pytanie dotyczyło używania kontenerów widoku, a nie kontrolerów widoku dziecka w ogóle. –

+0

OK w moim przypadku używam widoku kontenera, aby dodać kontroler widoku podrzędnego. Najpierw otrzymuję odwołanie do utworzonego kontrolera widoku podrzędnego w - (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender, a następnie dekoduję i koduję ręcznie, jak wyjaśniłem wcześniej. –

+0

Czy istnieje sposób dekodowania stanu MyChildViewController, który wywołuje [super decodeRestorableStateWithCoder: koder] we własnym - (void) decodeRestorableStateWithCoder: (NSCoder *) koder? Na przykład chcę użyć MyChildViewController jako kontroler widoku podrzędnego i jednocześnie jako niezależny kontroler widoku (użyj jako parametr w pushViewController). – diimdeep

15

widok Pojemnik kontroler "nie automatycznie zapisywać odniesień do jakichkolwiek zawierał kontrolerów widoku dziecko. Jeśli wdrożenie kontrolera widoku niestandardowym pojemnik, należy zakodować sterownik widok dziecko sprzeciwia się, jeśli chcesz, żeby być zachowane

Istnieją proste zasady, które znalazłem.

1.Embedded (dziecko) kontroler widoku powinien już być utworzony i dodany do nadrzędnego kontrolera widoku w procesie konserwacji stanu.Tak więc nie musisz nic robić, jeśli używasz storyboardu, w przeciwnym razie będziesz musiał utworzyć instancję kontrolera widoku podrzędnego i dodać go ręcznie:

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

Możesz dodać widok dziecka pod -viewDidLoad o r później. Użyj do tego celu self.childVC.view.frame = [self frameForChildController]; [self.view addSubview:self.childVC.view];.

2.You bez konieczności ratowania kontroler widoku dziecko rodzica -encodeRestorableStateWithCoder: siebie, ale trzeba kodować odniesienie do tego obiektu za pomocą -encodeObject:forKey:. Jeśli masz odniesienie można zrobić to tak:

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

zobaczyć https://stackoverflow.com/a/13279703/2492707 aby uzyskać odwołanie do dziecięcej VC jeśli używasz Storyboard. Czy można napisać coś prostego tak:

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

3. wbudowania (dziecko) Widok kontroler powinien być już utworzony i dodany do widoku nadrzędnego regulatora w procesie przywracania stanu. Tak więc, jeśli zrobiłeś wszystko w pierwszym akapicie, nie ma tu nic więcej do zrobienia.

4. "Jednak w tym przypadku nie dekoduję kontrolera widoku podrzędnego: możemy może, ale w rzeczywistości nie potrzebujemy go.Obiekt MyChildViewController przywróci własny stan. Mamy tylko zakodowane to odniesienie w celu uzyskania runtime chodzić łańcuch do instancji MyChildViewController i oszczędzają i-przywrócić na nim”.

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

This książka pomaga mi do zrozumienia zachowania stanu z widokiem kontenerowych. również look za dobry przykład dla tej książki

+1

Podsumowując to, jeśli używasz widoku kontenera storyboard (ten z osadzonym segue), wszystko co musisz zrobić, to wywołać 'encodeObject: forKey:' z dzieckiem z rodzica 'encodeRestorableStateWithCoder:'. Najlepszy sposób uzyskania odniesienia do dziecka znajduje się w 'prepareForSegue: sender:' dla embed segue. Nie trzeba dekodować dziecka ręcznie, ponieważ proces przywracania odnajdzie już istniejące dziecko i przywróci jego stan z archiwum. Jeśli jednak nie używasz storyboardu (tzn. Dodaje dzieci ręcznie), może zaistnieć potrzeba również zaimplementowania tego mechanizmu wyszukiwania. –

+0

Mówisz, że wbudowany kontroler podrzędny powinien być już utworzony i dodany do widoku nadrzędnego w procesie przywracania stanu. Ale w jaki sposób możemy uzyskać do niego dostęp? Ponieważ, jeśli jest już utworzony, nie powinno się tego robić ponownie w viewDidLoad, jak pokazałeś – markusian

Powiązane problemy