मैंने हमेशा "इसे एक सबव्यू के रूप में जोड़ें" समाधान असंतोषजनक पाया है, क्योंकि यह (1) ऑटोलॉयउट, (2) @IBInspectable
, और (3) आउटलेट के साथ शिकंजा है । इसके बजाय, मैं आपको awakeAfter:
एक NSObject
विधि के जादू से परिचित कराता हूं ।
awakeAfter
आपको वास्तव में पूरी तरह से एक अलग वस्तु के साथ एक एनआईबी / स्टोरीबोर्ड से जागने वाली वस्तु को स्वैप करने देता है। उस वस्तु को तब जलयोजन प्रक्रिया के माध्यम से रखा awakeFromNib
जाता है, उस पर बुलाया जाता है, एक दृश्य के रूप में जोड़ा जाता है, आदि।
हम अपने दृश्य के "कार्डबोर्ड कट-आउट" उपवर्ग में इसका उपयोग कर सकते हैं, जिसका एकमात्र उद्देश्य एनआईबी से दृश्य लोड करना और स्टोरीबोर्ड में उपयोग के लिए इसे वापस करना होगा। तब एम्बेड करने योग्य उपवर्ग मूल वर्ग के बजाय स्टोरीबोर्ड दृश्य के पहचान निरीक्षक में निर्दिष्ट होता है। यह वास्तव में काम करने के लिए एक उपवर्ग होने की जरूरत नहीं है, लेकिन यह एक उपवर्ग बना रही है जो आईबी को किसी भी IBInspectable / IBOutlet गुणों को देखने की अनुमति देता है।
यह अतिरिक्त बॉयलरप्लेट सब-अप्टीमल लग सकता है - और एक मायने में, क्योंकि आदर्श UIStoryboard
रूप से इस मूल को संभालना होगा - लेकिन मूल एनआईबी और UIView
उपवर्ग को पूरी तरह से अनअमोडिफाइड छोड़ने का फायदा है । यह जो भूमिका निभाता है वह मूल रूप से एक एडेप्टर या ब्रिज क्लास की है, और यह पूरी तरह से वैध, डिज़ाइन-वार है, अतिरिक्त वर्ग के रूप में, भले ही यह अफसोसजनक हो। दूसरी तरफ, यदि आप अपनी कक्षाओं से पारंगत होना पसंद करते हैं, तो कुछ अन्य छोटे बदलावों के साथ एक प्रोटोकॉल को लागू करके @ बेनपैच का समाधान काम करता है। प्रोग्रामर शैली के मामले में कौन से समाधान बेहतर उबाल है: क्या कोई वस्तु रचना या एकाधिक विरासत पसंद करता है।
नोट: NIB फ़ाइल में दृश्य पर सेट किया गया वर्ग समान रहता है। एम्बेड करने योग्य उपवर्ग केवल स्टोरीबोर्ड में उपयोग किया जाता है। उपवर्ग का उपयोग कोड में दृश्य को तुरंत करने के लिए नहीं किया जा सकता है, इसलिए इसमें कोई अतिरिक्त तर्क नहीं होना चाहिए, स्वयं। यह चाहिए केवल शामिल awakeAfter
हुक।
class MyCustomEmbeddableView: MyCustomView {
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
return (UIView.instantiateViewFromNib("MyCustomView") as MyCustomView?)! as Any
}
}
Is यहाँ एक महत्वपूर्ण कमी यह है कि यदि आप स्टोरीबोर्ड में चौड़ाई, ऊँचाई, या पहलू अनुपात को परिभाषित करते हैं जो किसी अन्य दृश्य से संबंधित नहीं है, तो उन्हें मैन्युअल रूप से कॉपी करना होगा। दो दृष्टिकोणों से संबंधित बाधाएं निकटतम सामान्य पूर्वजों पर स्थापित की जाती हैं, और विचार स्टोरीबोर्ड से अंदर-बाहर से जगाए जाते हैं, इसलिए जब तक उन बाधाओं को पर्यवेक्षी पर हाइड्रेटेड नहीं किया जाता है तब तक स्वैप पहले ही हो चुका है। बाधाएँ जो केवल प्रश्न में दृश्य को शामिल करती हैं, सीधे उस दृश्य पर स्थापित की जाती हैं, और जब स्वैप की प्रतिलिपि बनाई जाती है, तो इस तरह से फेंक दिया जाता है।
ध्यान दें कि यहां क्या हो रहा है , स्टोरीबोर्ड में दृश्य पर स्थापित बाधाएं नए तात्कालिक दृश्य में कॉपी की जाती हैं , जो पहले से ही अपनी स्वयं की बाधाओं हो सकती हैं, इसकी नीब फ़ाइल में परिभाषित की गई हैं। जो अप्रभावित हैं।
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
के लिए एक प्रकार-सुरक्षित एक्सटेंशन है UIView
। यह सब एनआईबी की वस्तुओं के माध्यम से लूप है जब तक कि यह उस प्रकार से मेल खाने वाले को नहीं पाता है। ध्यान दें कि जेनेरिक प्रकार रिटर्न वैल्यू है, इसलिए कॉल साइट पर टाइप को निर्दिष्ट करना होगा।
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
}
}