Bagaimana cara kerja View Controller Containment di iOS 5?

108

Di WWDC 2011 Sesi 102, Apple memperkenalkan View Controller Containment, yang adalah kemampuan untuk membuat wadah pengendali tampilan kustom, analog dengan UITabBarController, UINavigationController, dan sejenisnya.

Saya melihat contoh beberapa kali. Ada banyak metode yang terkait dengan pola ini, tetapi agak sulit untuk mengetahuinya dengan tepat. Saya akan memposting di sini apa yang saya pikir sedang terjadi dan melihat apakah komunitas akan mengkonfirmasi atau menghilangkan kecurigaan saya.

Skenario 1: Pindah dari tanpa induk ke pengontrol tampilan induk baru

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

Apakah dua baris pertama harus muncul dalam urutan yang ditentukan, atau dapatkah dibalik?

Skenario 2: Berpindah dari pengontrol tampilan induk ke tanpa pengontrol tampilan induk

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

Apakah perlu juga menelepon [vc didMoveToParentViewController:nil]? Contoh di Sesi 102 tidak melakukan hal ini dalam skenario ini, tetapi saya tidak tahu apakah itu kelalaian atau tidak.

Skenario 3: Berpindah dari satu pengontrol tampilan induk ke yang lain

Ini kemungkinan akan terjadi dengan cara berikut, karena logika di setiap pengontrol tampilan induk akan dienkapsulasi.

// 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];

Pertanyaan

Pertanyaan utama saya adalah ini: Apakah ini cara kerja penahanan pengontrol tampilan, secara umum? Apakah mekanisme yang diberikan di atas benar?

Apakah perlu menelepon willMoveToParentViewControllersebelum menelepon addChildViewController? Ini sepertinya urutan yang logis bagi saya, tetapi apakah ini benar-benar diperlukan?

Apakah perlu menelepon didMoveToParentViewController:nilsetelah menelepon removeFromParentViewController?

Gregory Higley
sumber

Jawaban:

72

The UIViewControllerdocs cukup jelas tentang kapan dan kapan tidak panggilan willMove/ didMovemetode. Lihat dokumentasi "Menerapkan Pengontrol Tampilan Penampung" .

Dokumen mengatakan, bahwa jika Anda tidak menimpa addChildViewController, Anda tidak perlu memanggil willMoveToParentViewController:metode. Namun Anda perlu memanggil didMoveToParentViewController:metode tersebut setelah transisi selesai. "Demikian pula, adalah tanggung jawab pengontrol tampilan penampung untuk memanggil willMoveToParentViewController:metode sebelum memanggil removeFromParentViewControllermetode. removeFromParentViewControllerMetode tersebut memanggil didMoveToParentViewController:metode pengontrol tampilan anak."

Juga, ada contoh yang dikerjakan di sini dan contoh kode di sini .

Semoga berhasil

timthetoolman
sumber
17
Begitu ya, jadi addChildViewControllerharus diimbangi dengan didMoveToParentViewControllerdan willMoveToParentViewControllerharus diimbangi dengan removeFromParentViewController. Inilah yang saya cari. Tidak yakin bagaimana saya melewatkannya di dokumen.
Gregory Higley
Kenapa tidak? Mengapa Anda tidak perlu memanggil willMoveToParentViewController tetapi harus memanggil didMoveToParentViewController?
pengguna4951
Karena itulah yang dikatakan oleh dokumen itu. Apple jelas merasa kita tidak perlu tahu.
7
Alasannya adalah demi animasi: Katakanlah Anda membuat pengontrol navigasi Anda sendiri. Pada awal animasi slide-in, 'willMove' perlu dipanggil, dan di akhir animasi, 'didMove' perlu dipanggil. Sekarang ketika Anda memanggil 'addChild' di awal animasi, itu secara otomatis memanggil 'willMove' untuk Anda. Tetapi tidak dapat mengetahui kapan animasi (jika ada) selesai, jadi Anda harus memanggil 'didMove' secara manual di akhir animasi (atau langsung tanpa animasi).
Chris
2
Dan untuk animasi 'geser keluar', misalnya anak sedang dihapus, Anda harus memanggil 'willMove' secara manual di awal animasi, karena uikit tidak akan tahu kapan harus memanggil 'viewWillDisappear' VC anak Anda. Dan di akhir animasi, saat Anda memanggil removeFromParentViewController, ia bisa memanggil 'didMove' secara otomatis untuk Anda.
Chris
23

Bagian ini tidak benar:

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

Menurut dokumen:

Saat container kustom Anda memanggil metode addChildViewController:, secara otomatis akan memanggil metode willMoveToParentViewController: pada pengontrol tampilan untuk ditambahkan sebagai anak sebelum menambahkannya.

Jadi, Anda tidak perlu [vc willMoveToParentViewController:self]ditelepon. Ini dilakukan secara otomatis saat Anda menelepon [self addChildViewController:vc]. Berikut contoh kodenya lagi:

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

Untuk menghapus pengontrol tampilan:

Metode removeFromParentViewController secara otomatis memanggil metode didMoveToParentViewController: dari pengontrol tampilan anak setelah menghapus anak.

Agaknya panggilan ini [oldVC didMoveToParentViewController:nil].

[vc willMoveToParentViewController:nil];
[vc.view removeFromSuperview];
[vc removeFromParentViewController];
// [vc didMoveToParentViewController:nil] called automatically
raja nevan
sumber
tampaknya jika dilakukan sebaliknya, meskipun tampaknya berfungsi, presentingViewController tidak disetel pada presentViewController.
Adrian
Dokumen mengatakan panggilan didMoveToParentViewController " segera setelah memanggil metode addChildViewController:", ini tidak menentukan kapan Anda benar-benar menambahkan subview anak. Saya ingin tahu apakah semua orang salah paham. Apakah ada contoh di beberapa Apple Docs yang dapat kami periksa?
Robert
Catatan: Anda lakukan perlu menelepon willMoveToParentViewControllersebelum addChildViewControllerjika item yang Anda bergerak adalah kelas kustom dengan ditimpa addChildViewController(kecuali override Anda menyebutnya internal)
bunkerdive