Mencari untuk memahami siklus hidup iOS UIViewController

299

Bisakah Anda menjelaskan kepada saya cara yang benar untuk mengelola UIViewControllersiklus hidup?

Secara khusus, saya ingin tahu bagaimana menggunakan Initialize, ViewDidLoad, ViewWillAppear, ViewDidAppear, ViewWillDisappear, ViewDidDisappear, ViewDidUnloaddan Disposemetode dalam Mono Sentuh untuk UIViewControllerkelas.

Lorenzo B
sumber
Apakah ada informasi atau tautan untuk OSX ViewController dan WindowController? Silakan bagikan.
Anoop Vaidya

Jawaban:

410

Semua perintah ini dipanggil secara otomatis pada waktu yang tepat oleh iOS ketika Anda memuat / menyajikan / menyembunyikan pengontrol tampilan. Penting untuk dicatat bahwa metode ini melekat UIViewControllerdan bukan untuk UIViewdiri mereka sendiri. Anda tidak akan mendapatkan salah satu fitur ini hanya dengan menggunakan a UIView.

Ada dokumentasi bagus di situs Apple di sini . Memasukkan secara sederhana:

  • ViewDidLoad- Dipanggil saat Anda membuat kelas dan memuat dari xib. Bagus untuk pengaturan awal dan hanya bekerja satu kali saja.

  • ViewWillAppear- Dipanggil tepat sebelum tampilan Anda muncul, bagus untuk menyembunyikan / menampilkan bidang atau operasi apa pun yang Anda inginkan terjadi setiap kali sebelum tampilan terlihat. Karena Anda mungkin bolak-balik di antara tampilan, ini akan dipanggil setiap kali tampilan Anda akan muncul di layar.

  • ViewDidAppear - Dipanggil setelah tampilan muncul - tempat yang bagus untuk memulai animasi atau memuat data eksternal dari API.

  • ViewWillDisappear/ DidDisappear- Ide yang sama dengan ViewWillAppear/ ViewDidAppear.

  • ViewDidUnload/ ViewDidDispose- Di Objective-C, ini adalah tempat Anda melakukan pembersihan dan pelepasan barang, tetapi ini ditangani secara otomatis sehingga tidak banyak yang benar-benar perlu Anda lakukan di sini.

Yakub Knobel
sumber
86
Teks ini sedikit menyesatkan, karena ViewDidLoad tidak boleh digunakan untuk pekerjaan satu kali saja. Mungkin dipanggil beberapa kali jika tampilan dibongkar karena kehabisan memori dan kemudian dimuat lagi.
Ricky Helgesson
4
ViewDidLoad sebenarnya tidak dipanggil ketika Anda membuat / menginisialisasi pengontrol tampilan. Ini disebut pertama kali Anda melakukan tampilan apa pun yang terkait dengan tampilan pengontrol tampilan. Seperti menambahkannya sebagai subview, mengatur bingkai, dll. Ini juga disebut tentu saja saat memuat dari nib.
Jason Grandelli
3
ViewDidAppear - Dipanggil setelah tampilan muncul - tempat yang bagus untuk memulai animasi atau memuat data eksternal dari API. Mengapa ini tempat yang baik untuk mulai memuat data? Mengapa tidak melihatDidLoad?
Anton Chikin
1
bagaimana dengan metode loadView, jika ini disebut pertama kali ketika sebuah nib dimuat dalam memori sebelum viewDidLoad atau tidak.
iHulk
@chakrit, ini adalah poin yang bagus - viewDidAppear adalah tempat yang tepat untuk menyegarkan data (jika perlu). Saya tidak setuju tentang KVO, karena dapat menyebabkan penyegaran yang tidak diinginkan pada pandangan yang tidak pernah benar-benar dilihat oleh pengguna.
Anton Chikin
409

PEMBARUAN: ViewDidUnload sudah tidak digunakan lagi di iOS 6, jadi perbarui jawabannya.

Daur hidup UIViewController digambarkan di sini:

Daur hidup pengontrol tampilan, diagram

Keuntungan menggunakan Xamarin Native / Mono Touch, adalah ia menggunakan API asli, dan karena itu mengikuti siklus hidup ViewController yang sama seperti yang Anda temukan di Dokumentasi Apple.

Haider
sumber
17
Di mana viewWillLayoutSubviews dan viewDidLayoutSubviews pergi di bagan alur ini?
Max_Power89
7
Diagram ini tidak akurat. viewDidUnload sudah tidak digunakan lagi sejak iOS6: stackoverflow.com/questions/12509102/…
occulus
2
Ini memang salah . Contoh lain dari jawaban yang salah di SO, seperti tahun-tahun berlalu. Komputasi sangat tidak statis.
Fattie
186

Ini untuk Versi iOS terbaru (Dimodifikasi dengan Xcode 9.3, Swift 4.1 ). Di bawah ini adalah semua tahapan yang membuat siklus hidup menjadi UIViewControllerlengkap.

  • loadView()

  • loadViewIfNeeded()

  • viewDidLoad()

  • viewWillAppear(_ animated: Bool)

  • viewWillLayoutSubviews()

  • viewDidLayoutSubviews()

  • viewDidAppear(_ animated: Bool)

  • viewWillDisappear(_ animated: Bool)

  • viewDidDisappear(_ animated: Bool)

Izinkan saya menjelaskan semua tahapan itu.

1. loadView

Acara ini membuat / memuat tampilan yang dikendalikan pengontrol. Itu dapat memuat dari file nib terkait atau kosong UIViewjika null ditemukan. Ini menjadikannya tempat yang bagus untuk membuat tampilan Anda dalam kode secara terprogram.

Di sinilah subclass harus membuat hierarki tampilan khusus mereka jika mereka tidak menggunakan nib. Seharusnya tidak pernah dipanggil secara langsung. Hanya timpa metode ini ketika Anda secara terprogram membuat tampilan dan menetapkan tampilan root ke viewproperti Jangan panggil metode super saat Anda mengganti loadView

2. loadViewIfNeeded

Jika memunculkan pandangan saat viewControllerini belum ditetapkan maka metode ini akan memuat tampilan tetapi ingat, ini hanya tersedia di iOS> = 9.0. Jadi, jika Anda mendukung iOS <9.0 maka jangan berharap itu masuk ke dalam gambar.

Memuat tampilan pengontrol tampilan jika belum ditetapkan.

3. viewDidLoad

The viewDidLoadevent hanya disebut ketika tampilan dibuat dan dimuat ke memori tapi batas untuk pandangan tidak didefinisikan belum. Ini adalah tempat yang baik untuk menginisialisasi objek yang akan digunakan pengontrol tampilan.

Dipanggil setelah tampilan dimuat. Untuk pengontrol tampilan yang dibuat dalam kode, ini adalah setelah-loadView. Untuk pengontrol tampilan yang tidak diarsipkan dari nib, ini setelah tampilan ditetapkan.

4. viewWillAppear

Acara ini memberi tahu viewControllerkapan saja tampilan muncul di layar. Pada langkah ini tampilan memiliki batas yang ditentukan tetapi orientasi tidak diatur.

Dipanggil saat tampilan hendak dibuat terlihat. Default tidak melakukan apa-apa.

5. viewWillLayoutSubviews

Ini adalah langkah pertama dalam siklus hidup tempat batas diselesaikan. Jika Anda tidak menggunakan kendala atau Tata Letak Otomatis, Anda mungkin ingin memperbarui subview di sini. Ini hanya tersedia di iOS> = 5.0. Jadi jika Anda mendukung iOS <5.0 maka jangan berharap itu masuk ke dalam gambar.

Disebut tepat sebelum metode layoutSubviews tampilan view controller dipanggil. Subkelas dapat diimplementasikan seperlunya. Standarnya adalah nop.

6. viewDidLayoutSubviews

Acara ini memberi tahu pengontrol tampilan bahwa subview telah disiapkan. Ini adalah tempat yang bagus untuk membuat perubahan pada subview setelah ditetapkan. Ini hanya tersedia di iOS> = 5.0. Jadi jika Anda mendukung iOS <5.0 maka jangan berharap itu masuk ke dalam gambar.

Disebut tepat setelah metode layoutSubviews tampilan view controller dipanggil. Subkelas dapat diimplementasikan seperlunya. Standarnya adalah nop.

7. viewDidAppear

The viewDidAppearperistiwa kebakaran setelah pandangan disajikan di layar. Yang menjadikannya tempat yang baik untuk mendapatkan data dari layanan backend atau database.

Disebut ketika tampilan telah sepenuhnya dialihkan ke layar. Default tidak melakukan apa-apa

8. viewWillDisappear

The viewWillDisappearperistiwa kebakaran ketika pandangan yang disajikan viewControlleradalah tentang menghilang, mengabaikan, menutupi atau menyembunyikan belakang lainnya viewController. Ini adalah tempat yang baik di mana Anda dapat membatasi panggilan jaringan Anda, membatalkan timer atau melepaskan objek yang terikat itu viewController.

Disebut ketika tampilan ditolak, ditutupi atau disembunyikan.

9. viewDidDisappear

Ini adalah langkah terakhir dari siklus hidup yang dapat diatasi oleh siapa saja karena peristiwa ini terjadi segera setelah tampilan yang disajikan viewControllertelah hilang, diberhentikan, ditutupi atau disembunyikan.

Dipanggil setelah pandangan ditolak, ditutupi atau disembunyikan. Default tidak melakukan apa-apa

Sekarang sesuai Apple ketika Anda menerapkan metode ini, Anda harus ingat untuk memanggil superimplementasi metode tertentu.

Jika Anda subkelas UIViewController, Anda harus memanggil super implementasi metode ini, bahkan jika Anda tidak menggunakan NIB. (Sebagai kenyamanan, metode init default akan melakukan ini untuk Anda, dan tentukan nihil untuk kedua argumen metode ini.) Dalam NIB yang ditentukan, proksi Pemilik File harus mengatur kelasnya ke subkelas pengontrol tampilan Anda, dengan outlet tampilan. terhubung ke tampilan utama. Jika Anda memanggil metode ini dengan nama nil nib, maka -loadViewmetode kelas ini akan mencoba memuat NIB yang namanya sama dengan kelas pengontrol tampilan Anda. Jika tidak ada NIB seperti itu, maka Anda harus memanggil -setView:sebelum -viewdipanggil, atau mengganti -loadViewmetode untuk mengatur tampilan Anda secara terprogram.

Semoga ini bisa membantu. Terima kasih.

UPDATE - Seperti @ThomasW menunjuk ke dalam komentar viewWillLayoutSubviewsdan viewDidLayoutSubviewsjuga akan dipanggil pada waktu lain ketika subview dari tampilan utama dimuat, misalnya ketika sel-sel tampilan tabel atau tampilan koleksi dimuat.

UPDATE - Seperti @Maria menunjuk ke dalam komentar, deskripsi loadViewtelah diperbarui

dalam penyelesaian
sumber
6
viewWillLayoutSubviewsdan viewDidLayoutSubviewsjuga akan dipanggil pada waktu lain ketika subview tampilan utama dimuat, misalnya ketika sel-sel tampilan tabel atau tampilan koleksi dimuat.
ThomasW
Ada sedikit kesalahan dalam jawaban ini: loadView () selalu dipanggil, tidak boleh ditimpa ketika view untuk controller dibuat di IB.
Maria
@Maria Silakan lanjutkan dan edit jawaban jika Anda pikir itu dapat ditingkatkan. Terima kasih.
Selesai
Default tidak ada yang salah untuk viewWillAppear viewDidAppear viewDidDisappear. Anda harus menelepon super di beberapa titik.
Mick
47

iOS 10,11 (Swift 3.1, Swift 4.0)

Menurut UIViewControllerdi UIKitpengembang,

1. loadView ()

Di sinilah subclass harus membuat hierarki tampilan khusus mereka jika mereka tidak menggunakan nib . Seharusnya tidak pernah dipanggil secara langsung.

2. loadViewIfNeeded ()

Memuat tampilan pengontrol tampilan jika belum ditetapkan.

3. viewDidLoad ()

Dipanggil setelah tampilan dimuat. Untuk pengontrol tampilan yang dibuat dalam kode, ini adalah setelah-loadView. Untuk pengontrol tampilan yang tidak diarsipkan dari nib, ini setelah tampilan ditetapkan.

4. viewWillAppear (_ animated: Bool)

Dipanggil saat tampilan hendak dibuat terlihat. Default tidak melakukan apa-apa

5. viewWillLayoutSubviews ()

Disebut tepat sebelum metode layoutSubviews tampilan view controller dipanggil. Subkelas dapat diimplementasikan seperlunya. Default tidak melakukan apa-apa.

6. viewDidLayoutSubviews ()

Disebut tepat setelah metode layoutSubviews tampilan view controller dipanggil. Subkelas dapat diimplementasikan seperlunya. Default tidak melakukan apa-apa.

7. viewDidAppear (_ animated: Bool)

Disebut ketika tampilan telah sepenuhnya dialihkan ke layar. Default tidak melakukan apa-apa

8. viewWillDisappear (_ animated: Bool)

Disebut ketika tampilan ditolak, ditutupi atau disembunyikan. Default tidak melakukan apa-apa

9. viewDidDisappear (_ animated: Bool )

Dipanggil setelah pandangan ditolak, ditutupi atau disembunyikan. Default tidak melakukan apa-apa

10. viewWillTransition (untuk ukuran: CGSize, dengan koordinator: UIViewControllerTransitionCoordinator)

Disebut ketika tampilan Transisi.

11. willMove (induk toParentViewController: UIViewController?)

12. didMove (induk toParentViewController: UIViewController?)

Kedua metode ini bersifat publik untuk subclass kontainer yang akan dipanggil saat transisi antara pengontrol anak. Jika ditimpa, penggantian harus memastikan untuk memanggil super.

Argumen induk dalam kedua metode ini adalah nol ketika seorang anak dikeluarkan dari induknya; selain itu sama dengan controller tampilan induk baru.

13. didReceiveMemoryWarning ()

Disebut ketika aplikasi induk menerima peringatan memori. Di iOS 6.0 tidak akan menghapus tampilan secara default.

Rajamohan S
sumber
2
Benar-benar sux bahwa stackoverflow tidak akan menghapus semua jawaban yang salah dan tidak lengkap dari seluruh utas ini. Jawaban Anda tampaknya lengkap sejauh metode panggilan pergi, jadi saya akan menganggap jawaban Anda sudah benar dan bekerja dengan itu.
Logicsaurus Rex
Apa yang nibdisebutkan di bawah ini loadView?
Petrus Theron
2
@ LogicsaurusRex Saya setuju. Dengan cara yang sama bahwa SO menandai pertanyaan sebagai duplikat atau dilindungi, saya pikir itu harus dapat menandai jawaban yang sudah usang atau usang
rmp251
Poin 5 di atas salah. viewWillLayoutSubviews()dipanggil sebelum objek tampilan ViewController memanggil layoutSubviews()metodenya
williamukoh
28

Mulai dari iOS 6 dan selanjutnya. Diagram baru adalah sebagai berikut:

masukkan deskripsi gambar di sini

Saad
sumber
1
Sebut tampilan itu "A". Pertimbangkan tampilan kedua "B" yang muncul saat "A" menghilang. Apakah "B.viewWillAppear" sebelum atau sesudah "A.viewDidDisappear"? Dan adakah situasi di mana urutan kedua perubahan itu?
ToolmakerSteve
Sepertinya tampilan baru (B) willApear akan dipanggil sebelum menghilang. Untuk pertanyaan kedua. Perlu waktu untuk melihatnya.
Saad
21

Mari kita berkonsentrasi pada metode, yang bertanggung jawab atas siklus hidup UIViewController :

  • Penciptaan:

    - (void)init

    - (void)initWithNibName:

  • Lihat pembuatan:

    - (BOOL)isViewLoaded

    - (void)loadView

    - (void)viewDidLoad

    - (UIView *)initWithFrame:(CGRect)frame

    - (UIView *)initWithCoder:(NSCoder *)coder

  • Penanganan perubahan kondisi tampilan:

    - (void)viewDidLoad

    - (void)viewWillAppear:(BOOL)animated

    - (void)viewDidAppear:(BOOL)animated

    - (void)viewWillDisappear:(BOOL)animated

    - (void)viewDidDisappear:(BOOL)animated

    - (void)viewDidUnload

  • Penanganan peringatan memori:

    - (void)didReceiveMemoryWarning

  • Deallokasi

    - (void)viewDidUnload

    - (void)dealloc

Diagram siklus hidup UIViewController

Untuk informasi lebih lanjut silakan lihat Referensi Kelas UIViewController .

Alexey Pelekh
sumber
19

Metode viewWillLayoutSubviewsdan viewDidLayoutSubviewstidak disebutkan dalam diagram, tetapi ini disebut antara viewWillAppeardan viewDidAppear. Mereka dapat dipanggil beberapa kali.

gjgjgj
sumber
Mereka juga akan dipanggil di waktu lain ketika subview tampilan utama dimuat, misalnya ketika sel-sel tampilan tabel atau tampilan koleksi dimuat.
ThomasW
16

Jawaban Haider benar untuk pra-iOS 6. Namun, pada iOS 6 viewDidUnload dan viewWillUnload tidak pernah dipanggil. The docs negara: "Tampilan tidak lagi dibersihkan dalam kondisi rendah memori dan jadi metode ini tidak pernah disebut."

Matt Becker
sumber
Saya mencoba meletakkan breakpoint di ViewWillDisappear, ViewDidDisappear, Buang. Tapi tidak ada dari mereka yang dipanggil ketika saya menavigasi dengan metode PresentViewController (). Apa yang bisa menjadi alasannya?
Sreeraj
1
Tautan tidak berfungsi ... Jadi, apa yang OS lakukan di bawah memori rendah?
Anak
Menyimpannya ke disk?
Ian Warburton
16

Ada banyak informasi yang ketinggalan zaman dan tidak lengkap di sini. Hanya untuk iOS 6 dan yang lebih baru:

  1. loadView[Sebuah]
  2. viewDidLoad[Sebuah]
  3. viewWillAppear
  4. viewWillLayoutSubviews adalah batas waktu pertama kali diselesaikan
  5. viewDidLayoutSubviews
  6. viewDidAppear
  7. * viewWillLayoutSubviews[b]
  8. * viewDidLayoutSubviews[b]

Catatan kaki:

(a) - Jika Anda secara manual menghilangkan tampilan selama didReceiveMemoryWarning, loadViewdan viewDidLoadakan dipanggil lagi. Yaitu, secara default loadViewdan viewDidLoadhanya dipanggil sekali per instance controller tampilan.

(B) Dapat disebut 0 kali tambahan atau lebih.

bobik
sumber
1
viewWillLayoutSubviewsdan viewDidLayoutSubviewsjuga akan dipanggil pada waktu lain ketika subview tampilan utama dimuat, misalnya ketika sel-sel tampilan tabel atau tampilan koleksi dimuat.
ThomasW
11

Menjelaskan Transisi Negara dalam dokumen resmi: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/index.html

Gambar ini menunjukkan transisi status yang valid antara berbagai metode panggilan balik 'akan' dan 'memang'

Transisi Negara yang Valid:


Diambil dari: https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Art/UIViewController Class Reference_2x.png

Luismi
sumber
0

Sesuai dokumen Apple - Mulai Kembangkan Aplikasi iOS (Swift) - Bekerja dengan View Controllers - Memahami Siklus Hidup View Controller

viewDidLoad()— Disebut ketika tampilan konten pengontrol tampilan (bagian atas hierarki tampilan) dibuat dan dimuat dari storyboard. ... Gunakan metode ini untuk melakukan pengaturan tambahan apa pun yang diperlukan oleh pengontrol tampilan Anda.

viewWillAppear()—Disebut sebelum tampilan konten pengontrol ditambahkan ke hierarki tampilan aplikasi. Gunakan metode ini untuk memicu operasi apa pun yang perlu terjadi sebelum tampilan konten disajikan di layar

viewDidAppear()—Disebut setelah tampilan konten pengontrol ditambahkan ke hierarki tampilan aplikasi. Gunakan metode ini untuk memicu operasi apa pun yang perlu terjadi segera setelah tampilan disajikan di layar, seperti mengambil data atau menampilkan animasi.

viewWillDisappear()—Disebut sebelum tampilan konten pengontrol dihapus dari hierarki tampilan aplikasi. Gunakan metode ini untuk melakukan tugas pembersihan seperti melakukan perubahan atau mengundurkan diri dari status responden pertama.

viewDidDisappear()—Disebut tepat setelah tampilan konten pengendali telah dihapus dari hierarki tampilan aplikasi. Gunakan metode ini untuk melakukan aktivitas teardown tambahan.

fred
sumber