Özel UIView Alt Sınıfı Örneği
Genelde film şeridi veya uç kullanmadan iOS uygulamaları oluşturuyorum. Sorularınıza cevap vermek için öğrendiğim bazı teknikleri paylaşacağım.
İstenmeyen initYöntemleri Gizleme
İlk önerim, UIViewistenmeyen başlatıcıları gizlemek için bir temel bildirmek . Bu yaklaşımı, "UI Alt Sınıflarında Storyboard ve Nib'e Özel Başlatıcıları Gizleme" yanıtımda ayrıntılı olarak tartıştım . Not: Bu yaklaşım BaseView, kasıtlı olarak uygulamanın çökmesine neden olacağından, hikaye tahtalarında veya uçlarda kullanmayacağınızı veya onun soyundan gelenleri kullanmayacağınızı varsayar .
class BaseView: UIView {
init() {
super.init(frame: CGRect.zero)
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
}
Özel UIView alt sınıfınız BaseView,. Başlatıcıda super.init () çağırmalıdır. Uygulanmasına gerek yoktur init(coder:). Bu, aşağıdaki örnekte gösterilmiştir.
UITextField Ekleme
Yöntemin dışında referans verilen alt görünümler için depolanmış özellikler oluşturuyorum init. Bunu genellikle bir UITextField için yapardım. Böyle Subview Mal bildiriminin içinde örneğini subviews tercih: let textField = UITextField().
UITextField, özel görünümün alt görünüm listesine arayarak eklemediğiniz sürece görünmez addSubview(_:). Bu, aşağıdaki örnekte gösterilmiştir.
Otomatik Düzen Olmadan Programatik Düzen
UITextField, boyutunu ve konumunu ayarlamadığınız sürece görünmeyecektir. Genellikle layoutSubviews yöntemi içinde kodda mizanpaj yapıyorum (Otomatik Yerleşimi kullanmıyorum) . layoutSubviews()başlangıçta ve bir yeniden boyutlandırma olayı olduğunda çağrılır. Bu, CustomView boyutuna bağlı olarak düzeni ayarlamaya izin verir. Örneğin, CustomView çeşitli iPhone ve iPad boyutlarında tam genişlikte görünüyorsa ve dönüş için ayarlama yapıyorsa, birçok başlangıç boyutunu barındırması ve dinamik olarak yeniden boyutlandırması gerekir.
Referans için CustomView boyutlarını almak için içinde frame.heightve frame.widthiçinde başvurabilirsiniz layoutSubviews(). Bu, aşağıdaki örnekte gösterilmiştir.
Örnek UIView Alt Sınıfı
Uygulanması gerekmeyen bir UITextField içeren özel bir UIView alt sınıfı init?(coder:).
class CustomView: BaseView {
let textField = UITextField()
override init() {
super.init()
textField.placeholder = "placeholder text"
textField.font = UIFont.systemFont(ofSize: 12)
addSubview(textField)
}
override func layoutSubviews() {
super.layoutSubviews()
textField.frame.size = CGSize(width: frame.width - 20, height: 30)
textField.frame.origin = CGPoint(x: 10, y: 10)
}
}
Otomatik Düzen ile Programatik Düzen
Kodda Otomatik Yerleşimi kullanarak da düzen uygulayabilirsiniz. Bunu sık sık yapmadığım için bir örnek göstermeyeceğim. Otomatik Yerleşimin uygulanmasına ilişkin örnekleri Stack Overflow'da ve internette başka yerlerde kodda bulabilirsiniz.
Programatik Düzen Çerçeveleri
Kodda düzen uygulayan açık kaynaklı çerçeveler vardır. İlgilendiğim ama denemediğim biri LayoutKit . LinkedIn geliştirme ekibi tarafından yazılmıştır. Github deposundan: "LinkedIn, LayoutKit'i yarattı çünkü Otomatik Yerleşimin kaydırılabilir görünümlerdeki karmaşık görünüm hiyerarşileri için yeterince performanslı olmadığını tespit ettik."
Koymak Neden fatalErroriçindeinit(coder:)
Bir film şeridinde veya uçta asla kullanılmayacak UIView alt sınıfları oluştururken, init(coder:)yöntem tarafından çağrılamayan farklı parametrelere ve başlatma gereksinimlerine sahip başlatıcılar sunabilirsiniz . Eğer init (kodlayıcı :) 'ı bir ile başaramadıysanız fatalError, yanlışlıkla bir storyboard / uçta kullanılırsa, çok kafa karıştırıcı sorunlara yol açabilir. FatalError bu niyetleri ileri sürer.
required init?(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
Alt sınıf oluşturulduğunda, kodda veya film şeridi / uçta oluşturulup oluşturulmadığına bakılmaksızın bir kod çalıştırmak istiyorsanız, aşağıdakine benzer bir şey yapabilirsiniz ( Jeff Gu Kang'ın cevabına göre )
class CustomView: UIView {
override init (frame: CGRect) {
super.init(frame: frame)
initCommon()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initCommon()
}
func initCommon() {
}
}