2011-12-05 5 views
103

Podczas konferencji WWDC 2011 Session 102 firma Apple wprowadziła kontroler View Control, który umożliwia tworzenie niestandardowych kontenerów kontrolerów widoku analogicznych do UITabBarController, UINavigationController i tym podobnych.Jak działa kontroler przeglądania w systemie iOS 5?

Obejrzałem przykłady kilka razy. Istnieje wiele metod związanych z tym wzorcem, ale trochę trudno było je dokładnie obliczyć. Zamierzam opublikować tutaj, o czym myślę, że się dzieje i zobaczyć, czy społeczność potwierdzi lub odrzuci moje podejrzenia.

Scenariusz 1: Przejście z żadnym z rodziców do nowego kontrolera widoku rodzica

[vc willMoveToParentViewController:self]; 
[self addChildViewController:vc]; 
[self.view addSubview:vc.view]; // or something like this. 
[vc didMoveToParentViewController:self]; 

Czy dwie pierwsze linie muszą wystąpić w podanej kolejności, lub mogą zostać odwrócone?

Scenariusz 2: Przejście z kontrolera do widoku macierzystego bez widoku nadrzędnego kontrolera

[vc willMoveToParentViewController:nil]; 
[vc.view removeFromSuperview]; 
[vc removeFromParentViewController]; 

Jest to również konieczne, aby zadzwonić [vc didMoveToParentViewController:nil]? Przykłady w sesji 102 nie zrobiły tego w tym scenariuszu, ale nie wiem, czy było to pominięcie, czy nie.

Scenariusz 3: Przejście z jednego nadrzędnego kontrolera widoku do innego

To prawdopodobnie pojawią się w następujący sposób, ponieważ logika w każdym widoku nadrzędnego regulatora zostanie zamknięta.

// In the old parent 
[vc willMoveToParentViewController:nil]; 
[vc.view removeFromSuperview]; 
[vc removeFromParentViewController]; 

// In the new parent 
[vc willMoveToParentViewController:self]; 
[self addChildViewController:vc]; 
[self.view addSubview:vc.view]; 
[vc didMoveToParentViewController:self]; 

Pytania

Moje główne pytanie brzmi: Czy to jak powstrzymywanie widok kontroler powinien działać w ogóle? Czy powyższa mechanika jest poprawna?

Czy należy dzwonić pod numer willMoveToParentViewController przed dzwonieniem pod numer addChildViewController? Wydaje mi się to logicznym porządkiem, ale czy jest to absolutnie konieczne?

Czy po zadzwonieniu pod numer removeFromParentViewController należy zadzwonić pod numer didMoveToParentViewController:nil?

+9

Problem polegał na tym, że gdy próbowałem dodać tag ios5, przypadkowo nacisnąłem klawisz enter, który dodał wpis, mimo że nie ukończyłem jego komponowania/edycji. Próbowałem go usunąć, ale potem stwierdziłem, że mogę tylko * głosować *, aby go usunąć. –

Odpowiedz

71

Dokumenty UIViewController są dość jasne, kiedy i kiedy nie należy wywoływać metod willMove/didMove. Sprawdź dokumentację "Implementing a Container View Controller".

Dokumenty mówią, że jeśli nie zastąpisz addChildViewController, nie musisz wywoływać metody willMoveToParentViewController:. Jednak po zakończeniu przejścia należy wywołać metodę didMoveToParentViewController:. "Podobnie, zadaniem kontrolera widoku kontenera jest wywołanie metody willMoveToParentViewController: przed wywołaniem metody removeFromParentViewController. Metoda removeFromParentViewController wywołuje metodę didMoveToParentViewController: kontrolera podrzędnego."

Istnieje również przykład wypracowany here i przykładowy kod here.

Powodzenia

+15

Rozumiem, więc 'addChildViewController' powinien być zrównoważony przez' didMoveToParentViewController', a 'willMoveToParentViewController' powinien być zbilansowany przez' removeFromParentViewController'. Właśnie tego szukałem. Nie wiem, jak to przegapiłem w dokumentach. –

+0

Dlaczego nie? Dlaczego nie musisz wywoływać metody willMoveToParentViewController, ale musisz zadzwonić do didMoveToParentViewController? –

+0

Bo tak mówią doktorzy. Apple oczywiście czuje, że nie musimy wiedzieć. –

21

Ta część nie jest poprawna:

[vc willMoveToParentViewController:self]; 
[self addChildViewController:vc]; 
[self.view addSubview:vc.view]; // or something like this. 
[vc didMoveToParentViewController:self]; 

According to the docs:

Gdy zwyczaj pojemnik wywołuje addChildViewController: metodę, automatycznie wywołuje willMoveToParentViewController: metoda widoku kontroler, który ma zostać dodany jako dziecko przed dodaniem.

Więc nie potrzebujesz połączenia [vc willMoveToParentViewController:self]. Robi się to automatycznie po wywołaniu [self addChildViewController:vc]. Oto przykładowy kod ponownie:

[self addChildViewController:vc]; 
// [vc willMoveToParentViewController:self] called automatically 
[self.view addSubview:vc.view]; // or something like this. 
[vc didMoveToParentViewController:self]; 

For removing view controllers:

Sposób removeFromParentViewController automatycznie wywołuje didMoveToParentViewController: metoda kontrolera widoku dziecko po to usuwa dziecko.

Prawdopodobnie jest to połączenie [oldVC didMoveToParentViewController:nil].

[vc willMoveToParentViewController:nil]; 
[vc.view removeFromSuperview]; 
[vc removeFromParentViewController]; 
// [vc didMoveToParentViewController:nil] called automatically 
+0

wydaje się, że jeśli zostanie wykonane inaczej, nawet jeśli wydaje się, że działa, prezentViewontroler nie jest ustawiony na presentViewController. – Adrian

+0

Dokumenty mówią, że wywołanie 'didMoveToParentViewController'" ** natychmiast ** po wywołaniu metody addChildViewController: "nie określa, kiedy faktycznie dodajesz podekomendę potomną. Zastanawiam się, czy wszyscy popełnili błąd. Czy jest jakiś przykład w niektórych dokumentach Apple, z którymi możemy to sprawdzić? – Robert

+0

Uwaga: * musisz * wywołać 'willMoveToParentViewController' przed' addChildViewController' jeśli element, który przenosisz, jest niestandardową klasą z nadpisanym 'addChildViewController' (chyba, że ​​twój override wywołuje to wewnętrznie) – bunkerdive