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 initMetode yang Tidak Diinginkan
Saran pertama saya adalah mendeklarasikan basis UIViewuntuk 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 menggunakan BaseViewatau turunannya di storyboard atau ujung karena ini akan menyebabkan aplikasi error secara sengaja.
class BaseView: UIView {
// This initializer hides init(frame:) from subclasses
init() {
super.init(frame: CGRect.zero)
}
// This attribute hides `init(coder:)` from subclasses
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
}
Subkelas UIView khusus Anda harus diwarisi dari BaseView. Itu harus memanggil super.init () di penginisialisasinya. Itu tidak perlu diimplementasikan init(coder:). Ini ditunjukkan pada contoh di bawah.
Menambahkan UITextField
Saya membuat properti yang disimpan untuk subview yang direferensikan di luar initmetode. 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.heightdan di frame.widthdalam layoutSubviews()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:).
class CustomView: BaseView {
let textField = UITextField()
override init() {
super.init()
// configure and add textField as subview
textField.placeholder = "placeholder text"
textField.font = UIFont.systemFont(ofSize: 12)
addSubview(textField)
}
override func layoutSubviews() {
super.layoutSubviews()
// Set textField size and position
textField.frame.size = CGSize(width: frame.width - 20, height: 30)
textField.frame.origin = CGPoint(x: 10, y: 10)
}
}
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 fatalErrordiinit(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 a fatalError, ini dapat menyebabkan masalah yang sangat membingungkan jika secara tidak sengaja digunakan dalam storyboard / nib. FatalError menegaskan maksud ini.
required init?(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
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 )
class CustomView: UIView {
override init (frame: CGRect) {
super.init(frame: frame)
initCommon()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initCommon()
}
func initCommon() {
// Your custom initialization code
}
}