Menutup Pengontrol Tampilan yang Disajikan


116

Saya punya pertanyaan teoretis. Sekarang, saya sedang membaca panduan ViewController Apple .

Mereka menulis:

Ketika tiba saatnya untuk menutup pengontrol tampilan yang disajikan, pendekatan yang disukai adalah membiarkan pengontrol tampilan yang menyajikan menutupnya. Dengan kata lain, jika memungkinkan, pengontrol tampilan yang sama yang menampilkan pengontrol tampilan juga harus bertanggung jawab untuk menutupnya. Meskipun ada beberapa teknik untuk memberi tahu pengontrol tampilan penyajian bahwa pengontrol tampilan yang disajikan harus ditutup, teknik yang disukai adalah pendelegasian.

Tapi saya tidak bisa menjelaskan, mengapa saya harus membuat protokol dalam VC yang disajikan dan menambahkan variabel delegasi, membuat metode delegasi dalam menyajikan VC untuk menolak VC yang disajikan, alih-alih panggilan sederhana dalam metode pengontrol tampilan yang disajikan

[self dismissViewControllerAnimated:NO completion:nil]?

Mengapa pilihan pertama lebih baik? Mengapa Apple merekomendasikannya?

Jawaban:


122

Saya pikir Apple sedikit menutupi punggung mereka di sini untuk sepotong API yang berpotensi kotor.

  [self dismissViewControllerAnimated:NO completion:nil]

Sebenarnya sedikit biola. Meskipun Anda dapat - secara sah - memanggil ini pada pengontrol tampilan yang disajikan, yang dilakukannya hanyalah meneruskan pesan ke pengontrol tampilan yang disajikan. Jika Anda ingin melakukan sesuatu di atas dan di atas hanya dengan mengabaikan VC, Anda perlu mengetahui hal ini, dan Anda perlu memperlakukannya dengan cara yang sama seperti metode delegasi - karena memang begitulah adanya, pemanggangan yang agak tidak fleksibel mendelegasikan metode.

Mungkin mereka telah menemukan banyak kode buruk oleh orang-orang yang tidak benar-benar memahami bagaimana ini disatukan, karenanya mereka berhati-hati.

Tapi tentu saja, jika yang perlu Anda lakukan hanyalah mengabaikannya, silakan.

Pendekatan saya sendiri adalah kompromi, setidaknya mengingatkan saya apa yang sedang terjadi:

  [[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]

[Cepat]

  self.presentingViewController?.dismiss(animated: false, completion:nil)

26
Perlu dicatat bahwa penggunaan presentingViewControllersebagian besar tidak berguna karena akan merujuk ke UINavigationControllerjika selftertanam di dalamnya . Dalam hal ini, Anda tidak akan bisa mendapatkan presentingViewControllersama sekali. Namun, [self dismissViewControllerAnimated:completion]masih berfungsi dalam kasus itu. Saran saya adalah terus menggunakannya sampai Apple memperbaikinya.
memmons

4
Saya suka bahwa jawaban ini masih relevan sepenuhnya 3 tahun kemudian.
pengguna1021430

1
Hal lain yang perlu dipertimbangkan adalah pengontrol tampilan tidak tahu bagaimana tampilannya. Ini mungkin telah disajikan, didorong ke pengontrol navigasi, bagian dari pengontrol bilah tab, dll. Menggunakan delegasi memungkinkan pengontrol tampilan "menyajikan" untuk "mengabaikan" pengontrol tampilan menggunakan kebalikan dari metode apa pun yang digunakan untuk menyajikannya.
David Smith

51

Diperbarui untuk Swift 3

Saya datang ke sini hanya ingin mengabaikan View Controller saat ini (disajikan). Saya membuat jawaban ini untuk siapa pun yang datang ke sini dengan tujuan yang sama.

Pengontrol Navigasi

Jika Anda menggunakan pengontrol navigasi, maka ini cukup mudah.

Kembali ke pengontrol tampilan sebelumnya:

// Swift
self.navigationController?.popViewController(animated: true)

// Objective-C
[self.navigationController popViewControllerAnimated:YES];

Kembali ke pengontrol tampilan root:

// Swift
self.navigationController?.popToRootViewController(animated: true)

// Objective-C
[self.navigationController popToRootViewControllerAnimated:YES];

(Berkat jawaban ini untuk Objective-C.)

Modal View Controller

Saat Pengontrol Tampilan disajikan secara sederhana, Anda dapat menutupnya (dari pengontrol tampilan kedua) dengan memanggil

// Swift
self.dismiss(animated: true, completion: nil)

// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];

The dokumentasi mengatakan,

Pengontrol tampilan presentasi bertanggung jawab untuk menutup pengontrol tampilan yang disajikan. Jika Anda memanggil metode ini pada pengontrol tampilan yang disajikan itu sendiri, UIKit meminta pengontrol tampilan yang menyajikan untuk menangani penutupan.

Jadi berfungsi untuk pengontrol tampilan yang disajikan untuk memanggilnya sendiri. Berikut contoh lengkapnya.

Delegasi

Pertanyaan OP adalah tentang kompleksitas penggunaan delegasi untuk menolak pandangan.

Untuk titik ini saya tidak perlu menggunakan delegasi karena saya biasanya memiliki pengontrol navigasi atau pengontrol tampilan modal, tetapi jika saya perlu menggunakan pola delegasi di masa mendatang, saya akan menambahkan pembaruan.


50

Ini untuk penggunaan kembali pengontrol tampilan.

Pengontrol tampilan Anda seharusnya tidak peduli jika itu disajikan sebagai modal, didorong pada pengontrol navigasi, atau apa pun. Jika pengontrol tampilan Anda menutup sendiri, Anda menganggapnya disajikan secara sederhana. Anda tidak akan dapat mendorong pengontrol tampilan tersebut ke pengontrol navigasi.

Dengan mengimplementasikan protokol, Anda membiarkan pengontrol tampilan induk memutuskan bagaimana protokol harus disajikan / didorong dan ditutup / dimunculkan.



6

Dalam pengalaman saya, ini berguna saat Anda perlu menutupnya dari ViewController mana pun yang Anda inginkan dan melakukan tugas berbeda untuk setiap viewcontroller yang menutupnya. Semua viewController yang mengadopsi protokol dapat menutup tampilan dengan caranya sendiri. (ipad vs iphone, atau meneruskan data yang berbeda saat menutup dari tampilan yang berbeda, memanggil metode yang berbeda saat menutup, dll ..)

Edit:

Jadi, untuk memperjelas, jika yang ingin Anda lakukan hanyalah mengabaikan tampilan, saya lihat tidak perlu menyiapkan protokol delegasi. Jika Anda perlu melakukan hal yang berbeda setelah Anda menutupnya dari pengontrol tampilan penyajian yang berbeda, Ini akan menjadi cara terbaik Anda untuk menggunakan delegasi.


tetapi jika saya tidak perlu "melewatkan data yang berbeda saat memberhentikan dari pandangan yang berbeda, memanggil metode yang berbeda saat memberhentikan, dll .." dapatkah saya melakukan satu panggilan kecil dalam metode pengontrol tampilan yang disajikan - [self dischargeViewControllerAnimated: NO penyelesaian: nil]?
nikitahils

Membiarkan penyaji menutup tampilan yang disajikan, memperjelas bahwa penyaji sebenarnya sudah siap dan menangani pengembalian ke latar depan: urutan eksekusi mudah diikuti, dan tanggung jawab pembaruan UI secara implisit jelas.
Johan

2

Kutipan dari Panduan Pemrograman Pengontrol Tampilan , "Bagaimana Pengontrol Tampilan Menampilkan Pengontrol Tampilan Lain".

Setiap pengontrol tampilan dalam rangkaian pengontrol tampilan yang disajikan memiliki petunjuk ke objek lain yang mengelilinginya dalam rangkaian tersebut. Dengan kata lain, pengontrol tampilan yang disajikan yang menampilkan pengontrol tampilan lain memiliki objek yang valid baik di properti presentingViewController maupun presentViewController. Anda bisa menggunakan hubungan ini untuk menelusuri rantai pengontrol tampilan sesuai kebutuhan. Misalnya, jika pengguna membatalkan operasi saat ini, Anda bisa menghapus semua objek dalam rantai dengan menutup pengontrol tampilan pertama yang disajikan. Menutup pengontrol tampilan akan menutup tidak hanya pengontrol tampilan tersebut, tetapi juga pengontrol tampilan apa pun yang disajikan.

Jadi di satu sisi itu membuat desain seimbang yang bagus, pelepasan yang baik, dll. Tapi di sisi lain itu sangat praktis, karena Anda dapat dengan cepat kembali ke titik tertentu dalam navigasi.

Meskipun, saya pribadi lebih suka menggunakan segue yang tidak berliku daripada mencoba menelusuri mundur pohon pengontrol tampilan yang ditampilkan, yang dibicarakan Apple dalam bab ini dari mana kutipan tersebut berasal.


2

Satu poin adalah bahwa ini adalah pendekatan pengkodean yang baik. Ini memenuhi banyak OOPprinsip, misalnya, SRP, Pemisahan kekhawatiran, dll.

Jadi, pengontrol tampilan yang menyajikan tampilan harus menjadi orang yang mengabaikannya.

Seperti, perusahaan real estat yang menyewakan rumah harus diberi wewenang untuk mengambilnya kembali.


2

Swift 3.0 // Singkirkan Pengontrol Tampilan dengan cepat

self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)

1

Selain jawaban Michael Enriquez, saya dapat memikirkan satu alasan lain mengapa ini mungkin cara yang baik untuk melindungi diri Anda dari keadaan yang tidak dapat ditentukan:

Katakanlah ViewControllerA menyajikan ViewControllerB secara sederhana. Namun, karena Anda mungkin belum menulis kode untuk ViewControllerA, Anda tidak mengetahui siklus hidup ViewControllerA. Ini mungkin menutup 5 detik (katakanlah) setelah menampilkan pengontrol tampilan Anda, ViewControllerB.

Dalam kasus ini, jika Anda hanya menggunakan dismissViewControllerdari ViewControllerB untuk menutupnya sendiri, Anda akan berakhir dalam keadaan tidak ditentukan - mungkin bukan crash atau layar hitam, tetapi keadaan tidak ditentukan dari sudut pandang Anda.

Sebaliknya, jika Anda menggunakan pola delegasi, Anda akan mengetahui status ViewControllerB dan Anda dapat memprogram untuk kasus seperti yang saya jelaskan.


1

Cepat

let rootViewController:UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!

        if (rootViewController.presentedViewController != nil) {
            rootViewController.dismiss(animated: true, completion: {
                //completion block.
            })
        }

0

Jika Anda menggunakan tampilan penggunaan modal, tutup.

[self dismissViewControllerAnimated:NO completion:nil];

Bagaimana ini menjawab pertanyaan: "Mengapa pilihan pertama lebih baik? Mengapa Apple merekomendasikannya?"
jww

0

Ini banyak omong kosong. Pendelegasian baik-baik saja jika diperlukan tetapi jika itu membuat kode lebih kompleks - dan memang demikian - maka perlu ada alasan untuk itu.

Saya yakin Apple punya alasannya sendiri. Tetapi lebih jelas dan lebih ringkas untuk hanya meminta VC yang disajikan melakukan pemecatan kecuali ada alasan yang benar untuk melakukan sebaliknya dan tidak ada seorang pun di sini hingga hari ini yang telah menyajikan yang dapat saya lihat.

Protokol sangat baik saat dibutuhkan tetapi desain berorientasi objek tidak pernah tentang memiliki modul yang saling berkomunikasi secara tidak perlu.

Tom Love (salah satu pengembang Objective C) pernah berkomentar bahwa Objective C "elegan", "kecil", "tajam" dan "terdefinisi dengan baik" (bila dibandingkan dengan C ++). Mudah baginya untuk mengatakannya. Delegasi adalah fitur berguna yang tampaknya telah digunakan secara berlebihan "hanya karena", dan sementara saya suka bekerja dalam bahasa tersebut, saya takut gagasan felling terpaksa menggunakan sintaks yang tidak perlu untuk membuat segalanya lebih kompleks daripada yang seharusnya.


Ini mungkin menghemat beberapa kode pada awalnya, tetapi pendekatan Anda akan menyebabkan banyak sakit kepala saat basis kode Anda tumbuh. Anda harus memahami prinsip-prinsip berorientasi objek seperti pemisahan masalah, jika tidak, Anda sebaiknya mengkodekan seluruh aplikasi Anda menjadi satu file besar.
Werner Altewischer

-2

Anda dapat Menutup jendela tampilan super Anda

self.view.superview?.window?.close()

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.