Apakah ada cara bawaan untuk mendapatkan dari a UIView
ke miliknya UIViewController
? Saya tahu Anda bisa mendapatkan dari UIViewController
ke-nya UIView
melalui [self view]
tapi saya bertanya-tanya apakah ada referensi terbalik?
sumber
Apakah ada cara bawaan untuk mendapatkan dari a UIView
ke miliknya UIViewController
? Saya tahu Anda bisa mendapatkan dari UIViewController
ke-nya UIView
melalui [self view]
tapi saya bertanya-tanya apakah ada referensi terbalik?
Karena ini sudah menjadi jawaban yang diterima sejak lama, saya merasa perlu memperbaikinya dengan jawaban yang lebih baik.
Beberapa komentar tentang kebutuhan:
Contoh cara menerapkannya adalah sebagai berikut:
@protocol MyViewDelegate < NSObject >
- (void)viewActionHappened;
@end
@interface MyView : UIView
@property (nonatomic, assign) MyViewDelegate delegate;
@end
@interface MyViewController < MyViewDelegate >
@end
Tampilan berinteraksi dengan delegasinya (seperti UITableView
halnya, misalnya) dan tidak peduli jika diterapkan di controller tampilan atau di kelas lain yang akhirnya Anda gunakan.
Jawaban asli saya berikut: Saya tidak merekomendasikan ini, baik sisa jawaban mana akses langsung ke pengontrol tampilan tercapai
Tidak ada cara bawaan untuk melakukannya. Meskipun Anda bisa mendapatkan sekitar itu dengan menambahkan IBOutlet
pada UIView
dan menghubungkan ini di Interface Builder, ini tidak dianjurkan. Pandangan seharusnya tidak tahu tentang pengontrol tampilan. Sebagai gantinya, Anda harus melakukan seperti yang disarankan oleh @Phil M dan membuat protokol untuk digunakan sebagai delegasi.
Menggunakan contoh yang diposting oleh Brock, saya memodifikasinya sehingga itu adalah kategori UIView, bukan UIViewController dan membuatnya rekursif sehingga setiap subview dapat (semoga) menemukan induk UIViewController.
Untuk menggunakan kode ini, tambahkan ke file kelas baru (saya beri nama saya "UIKitCategories") dan hapus data kelas ... salin antarmuka @ ke header, dan implementasi @ ke file .m. Kemudian dalam proyek Anda, # impor "UIKitCategories.h" dan gunakan dalam kode UIView:
sumber
UIView
adalah subkelas dariUIResponder
.UIResponder
menjabarkan metode-nextResponder
dengan implementasi yang mengembalikannil
.UIView
mengganti metode ini, seperti yang didokumentasikan dalamUIResponder
(untuk beberapa alasan, bukan dalamUIView
) sebagai berikut: jika tampilan memiliki pengontrol tampilan, itu dikembalikan oleh-nextResponder
. Jika tidak ada view controller, metode ini akan mengembalikan superview.Tambahkan ini ke proyek Anda dan Anda siap untuk roll.
Sekarang
UIView
memiliki metode yang berfungsi untuk mengembalikan pengontrol tampilan.sumber
UIView
dan penerimaUIViewController
. Jawaban Phil M menampilkan rekursi adalah jalan yang harus ditempuh.Saya akan menyarankan pendekatan yang lebih ringan untuk melintasi rantai responden lengkap tanpa harus menambahkan kategori pada UIView:
sumber
Menggabungkan beberapa jawaban yang sudah diberikan, saya mengirimnya juga dengan implementasi saya:
Kategori ini adalah bagian dari pustaka statis berkemampuan ARC yang saya kirimkan pada setiap aplikasi yang saya buat. Sudah diuji beberapa kali dan saya tidak menemukan masalah atau kebocoran.
PS: Anda tidak perlu menggunakan kategori seperti yang saya lakukan jika pandangan yang bersangkutan adalah subkelas dari Anda. Dalam kasus terakhir, cukup masukkan metode ini ke dalam subkelas Anda dan Anda siap melakukannya.
sumber
Meskipun ini secara teknis dapat diselesaikan seperti rekomendasi pgb , IMHO, ini adalah cacat desain. Tampilan tidak perlu mewaspadai pengontrol.
sumber
Saya memodifikasi de answer sehingga saya bisa memberikan tampilan, tombol, label dll. Untuk mendapatkan orang tua itu
UIViewController
. Ini kode saya.Edit Versi Swift 3
Sunting 2: - Ekstensi Swift
sumber
Jangan lupa bahwa Anda bisa mendapatkan akses ke pengendali tampilan root untuk jendela yang tampilannya adalah subview. Dari sana, jika Anda mis. Menggunakan pengontrol tampilan navigasi dan ingin mendorong tampilan baru ke dalamnya:
Anda perlu mengatur properti rootViewController dari jendela dengan benar terlebih dahulu. Lakukan ini saat pertama kali Anda membuat controller misalnya di delegasi aplikasi Anda:
sumber
[[self navigationController] view]
merupakan tampilan "utama" (sub) dari jendela,rootViewController
properti jendela harus diatur kenavigationController
yang mengontrol tampilan "utama" dengan segera.Meskipun jawaban ini secara teknis benar, termasuk Ushox, saya pikir cara yang disetujui adalah dengan mengimplementasikan protokol baru atau menggunakan kembali yang sudah ada. Protokol melindungi pengamat dari yang diamati, seperti menempatkan slot surat di antaranya. Akibatnya, itulah yang dilakukan Gabriel melalui pemanggilan metode pushViewController; tampilan "tahu" bahwa itu adalah protokol yang tepat untuk dengan sopan meminta navigationController Anda untuk mendorong tampilan, karena viewController sesuai dengan protokol navigationController. Meskipun Anda dapat membuat protokol sendiri, cukup gunakan contoh Gabriel dan gunakan kembali protokol UINavigationController.
sumber
Saya menemukan situasi di mana saya memiliki komponen kecil yang ingin saya gunakan kembali, dan menambahkan beberapa kode dalam tampilan yang dapat digunakan kembali sendiri (itu sebenarnya tidak lebih dari sebuah tombol yang membuka a
PopoverController
).Meskipun ini berfungsi dengan baik di iPad (
UIPopoverController
hadiah itu sendiri, karenanya tidak perlu referensi ke aUIViewController
), mendapatkan kode yang sama berfungsi berarti tiba-tiba merujuk AndapresentViewController
dari AndaUIViewController
. Agak tidak konsisten kan?Seperti disebutkan sebelumnya, itu bukan pendekatan terbaik untuk memiliki logika di UIView Anda. Tetapi rasanya benar-benar tidak berguna untuk membungkus beberapa baris kode yang diperlukan dalam pengontrol terpisah.
Bagaimanapun, inilah solusi cepat, yang menambahkan properti baru ke UIView apa pun:
sumber
Saya tidak berpikir itu "buruk" ide untuk mencari tahu siapa pengontrol tampilan untuk beberapa kasus. Apa yang bisa menjadi ide yang buruk adalah menyimpan referensi ke pengontrol ini karena dapat berubah seperti perubahan superviews. Dalam kasus saya, saya memiliki seorang pengambil yang melintasi rantai responden.
//.h
//.m
sumber
Simpel do while yang paling sederhana untuk menemukan viewController.
sumber
Cepat 4
(lebih ringkas daripada jawaban lainnya)
Kasus penggunaan saya yang saya perlu mengakses tampilan pertama
UIViewController
: Saya memiliki objek yang membungkusAVPlayer
/AVPlayerViewController
dan saya ingin memberikanshow(in view: UIView)
metode sederhana yang akanAVPlayerViewController
dimasukkan ke dalamview
. Untuk itu, saya perlu untuk mengaksesview
'sUIViewController
.sumber
Ini tidak menjawab pertanyaan secara langsung, tetapi membuat asumsi tentang maksud pertanyaan.
Jika Anda memiliki tampilan dan dalam tampilan itu Anda perlu memanggil metode pada objek lain, seperti katakanlah controller tampilan, Anda dapat menggunakan NSNotificationCenter sebagai gantinya.
Pertama buat string notifikasi Anda dalam file header
Dalam panggilan view postNotificationName panggilan Anda:
Kemudian di pengontrol tampilan, Anda menambahkan pengamat. Saya melakukan ini di viewDidLoad
Sekarang (juga di controller tampilan yang sama) mengimplementasikan metode copyString Anda: seperti yang digambarkan dalam pemilih @ di atas.
Saya tidak mengatakan ini adalah cara yang tepat untuk melakukan ini, sepertinya lebih bersih daripada menjalankan rantai responden pertama. Saya menggunakan kode ini untuk mengimplementasikan UIMenuController pada UITableView dan meneruskan kembali peristiwa tersebut ke UIViewController sehingga saya dapat melakukan sesuatu dengan data tersebut.
sumber
Ini tentu saja ide yang buruk dan desain yang salah, tapi saya yakin kita semua dapat menikmati solusi Swift dari jawaban terbaik yang diajukan oleh @Phil_M:
Jika niat Anda adalah untuk melakukan hal-hal sederhana, seperti menampilkan dialog modal atau melacak data, itu tidak membenarkan penggunaan protokol. Saya pribadi menyimpan fungsi ini dalam objek utilitas, Anda dapat menggunakannya dari apa pun yang mengimplementasikan protokol UIResponder sebagai:
Semua kredit ke @Phil_M
sumber
Mungkin saya terlambat ke sini. Tetapi dalam situasi ini saya tidak suka kategori (polusi). Saya suka seperti ini:
sumber
Solusi yang lebih cepat
sumber
sequence
bit). Jadi jika "cepat" berarti "lebih fungsional", maka saya kira itu lebih cepat.Versi terbaru untuk swift 4: Terima kasih atas @Phil_M dan @ paul-slm
sumber
Versi Swift 4
Contoh penggunaan
sumber
Dua solusi pada Swift 5.2 :
return
kata kunci sekarang 🤓Solusi 1:
Solusi 2:
sumber
Untuk jawaban Phil:
Sejalan:
id nextResponder = [self nextResponder];
jika diri (UIView) bukan subview dari pandangan ViewController, jika Anda tahu hierarki diri (UIView) Anda dapat menggunakan juga:id nextResponder = [[self superview] nextResponder];
...sumber
Solusi saya mungkin akan dianggap sebagai jenis palsu tetapi saya memiliki situasi yang sama dengan mayoneez (saya ingin mengalihkan pandangan sebagai tanggapan terhadap isyarat dalam EAGLView), dan saya mendapatkan pengontrol tampilan EAGL dengan cara ini:
sumber
EAGLViewController *vc = [(EAGLAppDelegate *)[UIApplication sharedApplication].delegate viewController];
.ClassName *object
- dengan tanda bintang.Saya pikir ada kasus ketika yang diamati perlu memberi tahu pengamat.
Saya melihat masalah yang sama di mana UIView dalam UIViewController merespons situasi dan pertama-tama perlu memberi tahu pengontrol tampilan induknya untuk menyembunyikan tombol kembali dan kemudian setelah selesai memberi tahu pengontrol tampilan induk bahwa ia perlu keluar dari tumpukan.
Saya telah mencoba ini dengan delegasi yang tidak berhasil.
Saya tidak mengerti mengapa ini ide yang buruk?
sumber
Cara mudah lain adalah memiliki kelas tampilan Anda sendiri dan menambahkan properti controller tampilan di kelas tampilan. Biasanya pengontrol tampilan membuat tampilan dan di sanalah pengontrol dapat mengatur sendiri ke properti. Pada dasarnya itu bukan mencari-cari (dengan sedikit peretasan) untuk controller, memiliki controller untuk mengatur sendiri ke tampilan - ini sederhana tetapi masuk akal karena itu adalah controller yang "mengontrol" tampilan.
sumber
Jika Anda tidak akan mengunggah ini ke App Store, Anda juga dapat menggunakan metode pribadi UIView.
sumber
sumber
Untuk mendapatkan pengontrol dari tampilan yang diberikan, seseorang dapat menggunakan rantai UIFirstResponder.
sumber
Jika rootViewController Anda adalah UINavigationViewController, yang dibuat di kelas AppDelegate, maka
Di mana c diperlukan kelas pengontrol tampilan.
PEMAKAIAN:
sumber
Tidak ada jalan.
Apa yang saya lakukan adalah meneruskan pointer UIViewController ke UIView (atau warisan yang sesuai). Maaf saya tidak bisa membantu dengan pendekatan IB untuk masalah karena saya tidak percaya pada IB.
Untuk menjawab komentator pertama: kadang-kadang Anda perlu tahu siapa yang memanggil Anda karena itu menentukan apa yang dapat Anda lakukan. Misalnya dengan database Anda mungkin hanya memiliki akses baca atau baca / tulis ...
sumber