Apakah Anda memiliki UIViewController yang besar? Bagi banyak orang, ya. Di satu sisi, ini berfungsi dengan data, di sisi lain - dengan antarmuka.
Tugas memisahkan logika dari antarmuka dijelaskan dalam ratusan artikel tentang arsitektur: MVP, MVVM, VIPER. Mereka memecahkan masalah aliran data, tetapi tidak menjawab pertanyaan tentang bagaimana bekerja dengan antarmuka: di satu tempat tetap ada penciptaan elemen, tata letak, konfigurasi, pemrosesan input dan animasi.
Mari kita pisahkan tampilan dari pengontrol dan lihat bagaimana loadView () membantu kita.

Antarmuka aplikasi untuk iOS adalah hierarki
UIView
. Tugas setiap
view
: membuat elemen, menyesuaikan, mengatur di tempat, menghidupkan. Ini bisa dilihat dari metode yang ada di kelas
UIView: addSubview(), drawRect(), layoutSubviews().
Jika Anda melihat metode kelas
UIViewController
, Anda dapat melihat bahwa ia mengelola
view:
memuat, merespons pemuatan layar, dan tindakan pengguna, menampilkan layar baru. Seringkali kode yang harus di
UIView
, kami menulis dalam subkelas dari
UIViewController
, ini membuatnya terlalu besar. Pisahkan itu.
loadView ()
Siklus hidup dari
UIViewController
dimulai dengan
loadView()
. Implementasi yang disederhanakan terlihat seperti ini:
Kita dapat mengganti metode dan menentukan kelas kita.
super.loadView()
tidak perlu dipanggil!
Implementasi CustomView.swift Pengontrol akan memuat
CustomView,
menambahkannya ke hierarki, mengekspos
.frame
. Properti
.view
akan menjadi kelas yang kita butuhkan:
Tetapi sementara kompiler tidak tahu tentang kelas dan percaya bahwa ada
UIView
normal. Mari kita perbaiki ini dengan fungsi tipe cor:
Sekarang Anda dapat melihat variabel
CustomView
:
Sederhanakan dengan tipe terkaitRuslan Kavetsky mengusulkan penghapusan duplikasi kode menggunakan ekspansi protokol:
protocol ViewSpecificController { associatedtype RootView: UIView } extension ViewSpecificController where Self: UIViewController { func view() -> RootView { return self.view as! RootView } }
Untuk setiap pengontrol baru, Anda hanya perlu menentukan protokol dan subkelas untuk UIView
melalui typealias
:
Kode dalam subkelas UIView
Membuat dan mengonfigurasi kontrol
Font, warna, konstanta, dan hierarki dapat diatur secara langsung di konstruktor CustomView:
layoutSubviews ()
Tempat terbaik untuk tata letak manual adalah metode
layoutSubviews()
. Disebut setiap kali ukuran
view
diubah, sehingga Anda dapat mengandalkan ukuran
bounds
untuk perhitungan yang benar:
Kontrol pribadi, properti publik
Jika ada waktu, maka saya membuat kontrol
property
pribadi, tetapi saya mengelolanya melalui variabel publik atau fungsi "di bidang pengetahuan". Contoh sederhana:
Keuntungan enkapsulasi: logika internal tersembunyi di balik antarmuka. Misalnya, validitas objek dapat ditunjukkan oleh warna area, bukan kotak, tetapi pengontrol tidak akan tahu apa-apa tentang itu.
Apa yang tersisa di viewDidLoad ()?
Jika Anda menggunakan Interface Builder, maka sering
viewDidLoad()
kosong. Jika Anda membuat
view
dalam kode, maka Anda harus mengikat tindakan mereka melalui pola aksi target, menambahkan
UIGestureRecognizer
atau mengikat delegasi.
Dapat dikustomisasi melalui Interface Builder
Subkelas untuk
view
dapat dikonfigurasi melalui Interface Builder (selanjutnya disebut IB).
Anda harus memilih objek
view
(bukan controller) dan mengatur kelasnya. Tidak perlu menulis
loadView()
Anda sendiri
loadView()
, controller akan melakukannya sendiri. Tetapi
UIView
masih harus
UIView
tipe
UIView
.

IBOutlet dalam UIView
Jika Anda memilih kontrol di dalam
view
, Asisten Editor mengenali kelas
UIView
dan menawarkannya sebagai file kedua dalam mode Otomatis. Jadi, Anda dapat mentransfer
IBOutlet
untuk
view
.

Jika tidak bekerjaBuka kelas
CustomView
secara manual, tulis
IBOutlet
. Sekarang Anda dapat menarik dengan penanda dan mengarahkan elemen di IB.

Jika Anda membuat antarmuka dalam kode, maka semua objek dapat diakses setelah
init()
, tetapi ketika bekerja dengan IB, akses ke
IBOutlet
hanya muncul setelah memuat antarmuka dari
UIStoryboard
dalam metode
awakeFromNib()
:
IBAction di UIViewController
Menurut selera saya, pengontrol harus meninggalkan semua tindakan pengguna. Dari standar:
- target-aksi dari kontrol
- delegasikan implementasi di
UIViewController
- memblokir implementasi
- reaksi terhadap
Notification
Dalam hal ini,
UIViewController
hanya mengontrol antarmuka. Segala sesuatu yang berkaitan dengan logika bisnis harus dikeluarkan dari controller, tetapi ini adalah pilihan: MVP, VIPER, dll.
Objektif-c
Di Objective-C, Anda dapat sepenuhnya mengganti tipe
UIView
. Untuk melakukan ini, deklarasikan properti dengan kelas yang diinginkan, ganti
setter
dan
getter
, tentukan kelas:
Akhirnya
Dalam contoh di GitHub, Anda dapat melihat pemisahan kelas untuk tugas sederhana: warna kotak tergantung pada posisinya (di area hijau itu hijau, di luar itu merah).
Semakin kompleks layar, semakin baik efeknya: pengontrol berkurang, kode ditransfer ke tempatnya. Kode hanya porting untuk
view
, tetapi enkapsulasi membuatnya mudah untuk berinteraksi dan membaca kode. Kadang-kadang
view
dapat digunakan kembali dengan pengontrol lain. Misalnya, berbagai pengontrol untuk iPhone dan iPad bereaksi dengan cara mereka sendiri terhadap tampilan keyboard, tetapi ini tidak mengubah kode
view
.
Saya menggunakan kode ini dalam proyek yang berbeda dan dengan orang yang berbeda, setiap kali tim menyambut penyederhanaan dan mengambil latihan. Saya harap Anda menikmatinya juga. Semua
UIViewController
mudah!