Saya ingin membuat subkelas UIView
dan menampilkan tampilan seperti login. Saya telah membuat ini di Objective-C, tetapi sekarang saya ingin memindahkannya ke Swift. Saya tidak menggunakan storyboard, jadi saya membuat semua UI saya dalam kode.
Tapi masalah pertama yang harus saya implementasikan initWithCoder
. Saya memberikannya implementasi default karena itu tidak akan dipanggil. Sekarang ketika saya menjalankan program itu macet, karena saya sudah menerapkannya initWithFrame
juga. Sekarang saya mendapatkan ini:
override init() {
super.init()
println("Default init")
}
override init(frame: CGRect) {
super.init(frame: frame)
println("Frame init")
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
println("Coder init")
}
Pertanyaan saya adalah di mana saya harus membuat textfield dll ... dan jika saya tidak pernah menerapkan frame dan coder bagaimana saya bisa "menyembunyikan" ini?
CGRectZero
saya percaya itu disarankan untuk digunakanCGRect.zeroRect
.Ini lebih sederhana.
sumber
Contoh Subclass UIView Kustom
Saya biasanya membuat aplikasi iOS tanpa menggunakan storyboard atau ujung pena. Saya akan membagikan beberapa teknik yang telah saya pelajari untuk menjawab pertanyaan Anda.
Menyembunyikan
init
Metode yang Tidak DiinginkanSaran pertama saya adalah mendeklarasikan basis
UIView
untuk menyembunyikan penginisialisasi yang tidak diinginkan. Saya telah membahas pendekatan ini secara rinci dalam jawaban saya untuk "Cara Menyembunyikan Papan Cerita dan Penginisialisasi Khusus Nib di Subkelas UI" . Catatan: Pendekatan ini mengasumsikan Anda tidak akan menggunakanBaseView
atau turunannya di storyboard atau ujung karena ini akan menyebabkan aplikasi error secara sengaja.Subkelas UIView khusus Anda harus diwarisi dari
BaseView
. Itu harus memanggil super.init () di penginisialisasinya. Itu tidak perlu diimplementasikaninit(coder:)
. Ini ditunjukkan pada contoh di bawah.Menambahkan UITextField
Saya membuat properti yang disimpan untuk subview yang direferensikan di luar
init
metode. Saya biasanya akan melakukannya untuk UITextField. Saya lebih suka subviews instantiate dalam deklarasi properti subview seperti ini:let textField = UITextField()
.UITextField tidak akan terlihat kecuali Anda menambahkannya ke daftar subview tampilan kustom dengan memanggil
addSubview(_:)
. Ini ditunjukkan pada contoh di bawah.Tata Letak Terprogram Tanpa Tata Letak Otomatis
UITextField tidak akan terlihat kecuali Anda menyetel ukuran dan posisinya. Saya sering melakukan layout dalam kode (tidak menggunakan Auto Layout) dalam metode layoutSubviews .
layoutSubviews()
dipanggil pada awalnya dan setiap kali terjadi peristiwa pengubahan ukuran. Ini memungkinkan penyesuaian tata letak tergantung pada ukuran CustomView. Misalnya, jika Tampilan Kustom muncul dengan lebar penuh di berbagai ukuran iPhone dan iPad dan menyesuaikan rotasi, ia perlu mengakomodasi banyak ukuran awal dan mengubah ukuran secara dinamis.Anda bisa merujuk ke
frame.height
dan diframe.width
dalamlayoutSubviews()
untuk mendapatkan dimensi CustomView sebagai referensi. Ini ditunjukkan pada contoh di bawah.Contoh Subclass UIView
Subclass UIView kustom yang berisi UITextField yang tidak perlu diimplementasikan
init?(coder:)
.Tata Letak Terprogram dengan Tata Letak Otomatis
Anda juga dapat mengimplementasikan tata letak menggunakan Tata Letak Otomatis dalam kode. Karena saya jarang melakukan ini, saya tidak akan menunjukkan contoh. Anda dapat menemukan contoh penerapan Tata Letak Otomatis dalam kode di Stack Overflow dan di tempat lain di Internet.
Kerangka Tata Letak Terprogram
Ada kerangka kerja sumber terbuka yang mengimplementasikan tata letak dalam kode. Salah satu yang saya minati tetapi belum pernah dicoba adalah LayoutKit . Itu ditulis oleh tim pengembangan dan LinkedIn. Dari gudang Github: "LinkedIn membuat LayoutKit karena kami menemukan bahwa Tata Letak Otomatis tidak cukup berfungsi untuk hierarki tampilan yang rumit dalam tampilan yang dapat digulir."
Mengapa menempatkan
fatalError
diinit(coder:)
Saat membuat subclass UIView yang tidak akan pernah digunakan di storyboard atau nib, Anda mungkin memperkenalkan penginisialisasi dengan parameter berbeda dan persyaratan inisialisasi yang tidak dapat dipanggil oleh
init(coder:)
metode. Jika Anda tidak gagal init (coder :) dengan afatalError
, ini dapat menyebabkan masalah yang sangat membingungkan jika secara tidak sengaja digunakan dalam storyboard / nib. FatalError menegaskan maksud ini.Jika Anda ingin menjalankan beberapa kode saat subclass dibuat terlepas dari apakah itu dibuat dalam kode atau storyboard / nib maka Anda dapat melakukan hal seperti berikut (berdasarkan jawaban Jeff Gu Kang )
sumber
fatalError
Anda melarang untukfatalError
di dalam metode dealloc dan memberi tahu kami bahwa itu tidak berfungsi karena kelas itu harus tunggal. Jika Anda lebih suka membuat elemen UI dalam kode maka Anda tidak boleh melarang secara manual semua cara lain. Akhirnya pertanyaannya adalah bagaimana membuat "secara terprogram tanpa papan cerita" tetapi xibs / nibs tidak disebutkan. Dalam kasus saya, saya perlu membuat array sel dengan secara terprogram + xib dan meneruskannya ke dalamnyaDropDownMenuKit
dan cara ini tidak berfungsi karena penulis pustaka ini juga melarang xibs.UIView Anda harus dibuat oleh pembuat antarmuka / storyboard atau dari kode. Saya merasa berguna memiliki
setup
metode untuk mengurangi duplikasi kode pengaturan apa pun. misalnyasumber
Swift 4.0, Jika Anda ingin menggunakan tampilan dari file xib, maka ini untuk Anda. Saya membuat kelas Sub kelas CustomCalloutView dari UIView. Saya telah membuat file xib dan di IB cukup pilih pemilik file kemudian pilih Atribut inspektur set nama kelas ke CustomCalloutView, lalu buat outlet di kelas Anda.
// Sekarang menambahkannya
sumber
Berikut adalah contoh bagaimana saya biasanya membangun subclass saya (UIView). Saya memiliki konten sebagai variabel sehingga mereka dapat diakses dan diubah mungkin nanti di kelas lain. Saya juga telah menunjukkan bagaimana saya menggunakan tata letak otomatis dan menambahkan konten.
Misalnya dalam ViewController saya memiliki tampilan ini diinisialisasi Dalam ViewDidLoad () karena itu hanya dipanggil sekali ketika tampilan terlihat. Kemudian saya menggunakan fungsi ini yang saya buat di sini
addContentToView()
dan kemudianactivateConstraints()
untuk membangun konten dan mengatur batasan. Jika saya nanti di ViewController ingin warna katakanlah tombol menjadi merah, saya hanya melakukannya di fungsi tertentu di ViewController itu. Sesuatu seperti:func tweaksome(){ self.customView.someButton.color = UIColor.red}
sumber