(1) otomatik düzen, (2) @IBInspectable
ve (3) çıkışları vidaladığı için "onu bir alt görünüm olarak ekle" çözümünü her zaman yetersiz buldum . Bunun yerine, size awakeAfter:
bir NSObject
yöntemin büyüsünü tanıtmama izin verin .
awakeAfter
bir NIB / Storyboard'dan gerçekten uyanmış olan nesneyi tamamen farklı bir nesneyle değiştirmenize izin verir. Bu nesne daha sonra hidrasyon sürecinden geçirilir, awakeFromNib
çağrılır, görünüm olarak eklenir vb.
Bunu, görünümümüzün "kartondan kesilmiş" bir alt sınıfında kullanabiliriz, bunun tek amacı görünümü NIB'den yüklemek ve Storyboard'da kullanmak üzere geri göndermek olacaktır. Gömülebilir alt sınıf daha sonra orijinal sınıf yerine Storyboard görünümünün kimlik denetçisinde belirtilir. Bunun çalışması için aslında bir alt sınıf olması gerekmez, ancak IB'nin herhangi bir IBInspectable / IBOutlet özelliğini görmesini sağlayan şey onu bir alt sınıf yapmaktır.
Bu ekstra standart şablon yetersiz görünebilir ve bir anlamda öyledir, çünkü ideal olarak UIStoryboard
bunu sorunsuz bir şekilde hallederdi - ancak orijinal NIB'yi ve UIView
alt sınıfı tamamen değiştirilmemiş bırakma avantajına sahiptir . Oynadığı rol temelde bir adaptör veya köprü sınıfının rolüdür ve üzücü olsa bile ek bir sınıf olarak tasarım açısından mükemmel bir şekilde geçerlidir. Diğer taraftan, sınıflarınızla sıkı sıkıya sarılmayı tercih ediyorsanız, @ BenPatch'in çözümü, diğer bazı küçük değişikliklerle bir protokol uygulayarak çalışır. Hangi çözümün daha iyi olduğu sorusu programcı tarzına indirgeniyor: Nesne kompozisyonu mu yoksa çoklu kalıtım mı tercih ediliyor?
Not: NIB dosyasındaki görünümde ayarlanan sınıf aynı kalır. Gömülebilir alt sınıf yalnızca film şeridinde kullanılır. Alt sınıf, görünümü kodda başlatmak için kullanılamaz, bu nedenle herhangi bir ek mantığı olmamalıdır. Bu olmalıdır yalnızca ihtiva awakeAfter
kanca.
class MyCustomEmbeddableView: MyCustomView {
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
return (UIView.instantiateViewFromNib("MyCustomView") as MyCustomView?)! as Any
}
}
⚠️ Buradaki önemli bir dezavantaj, film şeridinde başka bir görünümle ilgili olmayan genişlik, yükseklik veya en boy oranı kısıtlamalarını tanımlarsanız, bunların manuel olarak kopyalanması gerektiğidir. İki görünümü ilişkilendiren kısıtlamalar en yakın ortak ataya yüklenir ve görünümler içten dışa film şeridinden uyandırılır, bu nedenle bu kısıtlamalar süpervizör görünümünde sulandırıldığında takas zaten gerçekleşmiştir. Yalnızca söz konusu görünümü içeren kısıtlamalar doğrudan bu görünüme yüklenir ve bu nedenle, kopyalanmadıkları sürece takas gerçekleştiğinde atılır.
Burada olan şeyin, film şeridindeki görünümde yüklü olan kısıtlamaların, uç dosyasında tanımlanmış kendi kısıtlamalarına sahip olabilecek yeni örneklenmiş görünüme kopyalanması olduğuna dikkat edin . Bunlar etkilenmez.
class MyCustomEmbeddableView: MyCustomView {
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
let newView = (UIView.instantiateViewFromNib("MyCustomView") as MyCustomView?)!
for constraint in constraints {
if constraint.secondItem != nil {
newView.addConstraint(NSLayoutConstraint(item: newView, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: newView, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
} else {
newView.addConstraint(NSLayoutConstraint(item: newView, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: constraint.constant))
}
}
return newView as Any
}
}
instantiateViewFromNib
için tür güvenli bir uzantıdır UIView
. Tek yaptığı, türle eşleşen bir tane bulana kadar NIB'nin nesneleri arasında döngü yapmaktır. Genel türün dönüş değeri olduğuna dikkat edin , bu nedenle türün çağrı sitesinde belirtilmesi gerekir.
extension UIView {
public class func instantiateViewFromNib<T>(_ nibName: String, inBundle bundle: Bundle = Bundle.main) -> T? {
if let objects = bundle.loadNibNamed(nibName, owner: nil) {
for object in objects {
if let object = object as? T {
return object
}
}
}
return nil
}
}