Widok kontenera można łatwo dodać do scenorysu za pomocą edytora interfejsu. Po dodaniu widok kontenera jest widokiem zastępczym, osadzonym płynem i (podrzędnym) kontrolerem widoku.
Nie mogę jednak znaleźć sposobu na programowe dodanie widoku kontenera. Właściwie nie jestem nawet w stanie znaleźć klasy o UIContainerView
takiej nazwie .
Nazwa klasy Container View to z pewnością dobry początek. Kompletny przewodnik zawierający odcinek będzie bardzo mile widziany.
Znam Przewodnik programowania kontrolera, ale nie uważam go za taki sam, jak robi to Interface Builder dla Container Viewer. Na przykład, gdy ograniczenia są prawidłowo ustawione, widok (podrzędny) dostosuje się do zmian rozmiaru w widoku kontenera.
ios
cocoa-touch
subview
uicontainerview
childviewcontroller
Kod Dante May
źródło
źródło
ViewController
cykl życia elementów wbudowanych .ViewController
Cykl życia osadzonego przez Interface Builder jest normalny, ale ten dodany programowo nie maviewDidAppear
aniviewWillAppear(_:)
aniviewWillDisappear
.viewWillAppear
iviewWillDisappear
są wywoływane na kontrolerze widoku podrzędnego, w porządku. Jeśli masz przykład, w którym ich nie ma, powinieneś wyjaśnić lub zadać własne pytanie, pytając, dlaczego tak nie jest.Odpowiedzi:
„Widok kontenera” scenorysu to tylko standardowy
UIView
obiekt. Nie ma specjalnego typu „widoku kontenera”. W rzeczywistości, jeśli spojrzysz na hierarchię widoków, zobaczysz, że „widok kontenera” jest standardemUIView
:Aby osiągnąć to programowo, stosujesz „ograniczenie kontrolera widoku”:
instantiateViewController(withIdentifier:)
obiekt serii ujęć.addChild
do kontrolera widoku rodzica.view
do hierarchii widoku za pomocąaddSubview
(a także ustaw odpowiednioframe
ograniczenia lub).didMove(toParent:)
metodę na podrzędnym kontrolerze widoku, przekazując odwołanie do nadrzędnego kontrolera widoku.Zobacz implementowanie kontrolera widoku kontenera w Przewodniku programowania kontrolera widoku i sekcji „Implementowanie kontrolera widoku kontenera” w odwołaniu do klasy UIViewController .
Na przykład w Swift 4.2 może wyglądać tak:
Uwaga, powyższe w rzeczywistości nie dodaje „widoku kontenera” do hierarchii. Jeśli chcesz to zrobić, zrób coś takiego:
Ten ostatni wzorzec jest niezwykle przydatny, jeśli kiedykolwiek przechodzisz między różnymi kontrolerami widoku podrzędnego i chcesz się tylko upewnić, że widok jednego dziecka znajduje się w tej samej lokalizacji i widoku poprzedniego dziecka (tj. Wszystkie unikalne ograniczenia dla miejsca docelowego są podyktowane przez widok kontenera, zamiast za każdym razem przebudowywać te ograniczenia). Ale jeśli wykonujesz tylko proste zawarcie widoku, potrzeba tego oddzielnego widoku kontenera jest mniej przekonująca.
W powyższych przykładach zamierzam
translatesAutosizingMaskIntoConstraints
samodzielniefalse
zdefiniować ograniczenia. Oczywiście możesz pozostawićtranslatesAutosizingMaskIntoConstraints
jakotrue
i ustawić zarówno widok, jakframe
iautosizingMask
dla dodawanych widoków, jeśli wolisz.Zobacz poprzednie wersje tej odpowiedzi dla wersji Swift 3 i Swift 2 .
źródło
ViewController
cykl życia elementów wbudowanych .ViewController
Cykl życia osadzonego przez Interface Builder jest normalny, ale ten dodany programowo nie maviewDidAppear
aniviewWillAppear(_:)
aniviewWillDisappear
.ViewController
„yviewDidAppear
nazywa się w jego rodzicówviewDidLoad
, a nie podczas jego rodzicówviewDidAppear
viewDidAppear
, [ale] aniviewWillAppear(_:)
aniviewWillDisappear
". Wyświetlanewill
metody są wywoływane poprawnie w obu scenariuszach. Trzeba zadzwonićdidMove(toParentViewController:_)
, robiąc to programowo, ale inaczej nie zrobią. Odnośnie czasu pojawienia się. metody są wywoływane w tej samej kolejności w obie strony. Różni się jednak czasviewDidLoad
, ponieważ w przypadku osadzania jest ładowany wcześniejparent.viewDidLoad
, ale w przypadku programmatic, jak można się spodziewać, dzieje się to podczasparent.viewLoadLoad
.translatesAutoresizingMaskIntoConstraints = false
. Nie wiem, dlaczego jest to potrzebne ani dlaczego sprawia, że wszystko działa, ale dziękuję za uwzględnienie tego w odpowiedzi.@ Odpowiedź Roba w Swift 3:
źródło
Detale
Rozwiązanie
Stosowanie
Pełna próbka
Wyniki
źródło
tableViewController
w sposóbviewController
, ale nie można ustawić tytuł pierwszego. Nie wiem, czy da się to zrobić. Wysłałem to pytanie . Miło z twojej strony, jeśli na to spojrzysz.Oto mój kod w Swift 5.
}
Stosowanie
Użyj drugiej funkcji osadzania z kontrolerem widoku innym niż scenorys.
źródło
removeFromParent
zapobiega twoje wywołanie, jak zmodyfikowałbyś swoją klasę, aby na to zezwolić?