परमाणु डिजाइन और सिस्टम डिज़ाइन डिज़ाइन में लोकप्रिय हैं: यह वह है जब सब कुछ घटकों से होता है, नियंत्रण से लेकर स्क्रीन तक। एक प्रोग्रामर के लिए अलग-अलग नियंत्रण लिखना मुश्किल नहीं है, लेकिन पूरे स्क्रीन के साथ क्या करना है?
आइए नए साल के उदाहरण पर एक नज़र डालें:
- चलो सब कुछ एक साथ रहना;
- नियंत्रकों में विभाजित: नेविगेशन, टेम्पलेट और सामग्री का चयन करें;
- अन्य स्क्रीन के लिए पुन: उपयोग कोड।

सभी एक झुंड में
इस नए साल की स्क्रीन पिज़्ज़ेरिया के विशेष शुरुआती घंटों के बारे में बात करती है। यह काफी सरल है, इसलिए इसे एक नियंत्रक बनाना अपराध नहीं होगा:

लेकिन। अगली बार, जब हमें एक समान स्क्रीन की आवश्यकता होगी, तो हमें इसे फिर से दोहराना होगा, और फिर सभी स्क्रीन पर समान परिवर्तन करना होगा। खैर, यह संपादन के बिना नहीं होता है।
इसलिए, इसे भागों में विभाजित करना और अन्य स्क्रीन के लिए इसका उपयोग करना अधिक उचित है। मैंने तीन पर प्रकाश डाला:
- नेविगेशन,
- सामग्री के लिए एक क्षेत्र के साथ एक टेम्पलेट और स्क्रीन के नीचे कार्रवाई के लिए एक जगह,
- केंद्र में अद्वितीय सामग्री।
प्रत्येक भाग को अपने स्वयं के UIViewController
।
कंटेनर नेविगेशन
नेविगेशन कंटेनर के सबसे हड़ताली उदाहरण UINavigationController
और UITabBarController
। प्रत्येक व्यक्ति अपने स्वयं के नियंत्रण के तहत स्क्रीन पर एक पट्टी रखता है, और शेष स्थान को एक और UIViewController
लिए छोड़ देता है।
हमारे मामले में, केवल एक करीबी बटन के साथ सभी मोडल स्क्रीन के लिए एक कंटेनर होगा।
क्या बात है?यदि हम बटन को दाईं ओर ले जाना चाहते हैं, तो हमें केवल एक नियंत्रक में इसे बदलना होगा।
या, अगर हम एक विशेष एनीमेशन के साथ सभी मोडल विंडो को दिखाने का फैसला करते हैं, और एक कड़ी चोट के साथ इंटरएक्टिव रूप से बंद कर देते हैं, जैसा कि ऐपस्ट्रीम स्टोरी कार्ड में है। फिर UIViewControllerTransitioningDelegate
को केवल इस कंट्रोलर के लिए सेट करना होगा।

आप container view
को अलग करने के लिए एक container view
का उपयोग कर सकते हैं: यह माता-पिता में एक UIView
बनाएगा और उसमें बच्चे नियंत्रक UIView
सम्मिलित करेगा।

स्क्रीन के किनारे पर container view
। Safe area
स्वचालित रूप से बाल नियंत्रक पर लागू होगा:

स्क्रीन पैटर्न
सामग्री स्क्रीन पर स्पष्ट है: चित्र, शीर्षक, पाठ। बटन इसका हिस्सा लगता है, लेकिन विभिन्न आईफ़ोन पर सामग्री गतिशील है, और बटन तय हो गया है। विभिन्न कार्यों वाले दो सिस्टम दिखाई देते हैं: एक सामग्री प्रदर्शित करता है, और दूसरा इसे एम्बेड और संरेखित करता है। उन्हें दो नियंत्रकों में विभाजित किया जाना चाहिए।

पहला स्क्रीन के लेआउट के लिए ज़िम्मेदार है: सामग्री को केंद्रित किया जाना चाहिए, और स्क्रीन के नीचे बटन दबाया गया। दूसरा कंटेंट ड्रा करेगा।

एक टेम्पलेट के बिना, सभी नियंत्रक समान हैं, लेकिन तत्व नृत्य करते हैं।
अंतिम स्क्रीन के बटन अलग हैं - यह सामग्री पर निर्भर करता है। प्रतिनिधिमंडल समस्या को हल करने में मदद करेगा: नियंत्रक-टेम्पलेट सामग्री से नियंत्रण के लिए पूछेगा और उन्हें अपने UIStackView
में प्रदर्शित करेगा।
बटन को संबंधित वस्तुओं के माध्यम से नियंत्रक से जोड़ा जा सकता है। उनके IBOutlet
और IBAction
सामग्री नियंत्रक में संग्रहीत हैं, बस तत्वों को पदानुक्रम में नहीं जोड़ा गया है।

आप सामग्री से तत्व प्राप्त कर सकते हैं और उन्हें UIStoryboardSegue
की तैयारी के चरण में टेम्पलेट में जोड़ सकते हैं:
सेटर में, हम UIStackView
नियंत्रण UIStackView
:
नतीजतन, हमारे नियंत्रक को तीन भागों में विभाजित किया गया था: नेविगेशन, टेम्पलेट और सामग्री। तस्वीर में, सभी container view
ग्रे में दिखाए गए हैं:

गतिशील नियंत्रक आकार
सामग्री नियंत्रक का अपना अधिकतम आकार है, यह आंतरिक constraints
द्वारा सीमित है।
Container view
Autoresizing mask
आधार पर कॉन्स्टोर्स जोड़ता है, और वे सामग्री के आंतरिक आयामों के साथ संघर्ष करते हैं। समस्या कोड में हल की गई है: सामग्री नियंत्रक में, आपको यह इंगित करने की आवश्यकता है कि यह Autoresizing mask
से नक्षत्रों से प्रभावित नहीं है:

इंटरफ़ेस बिल्डर के लिए दो और चरण हैं:
चरण 1. UIView
लिए Intrinsic size
निर्दिष्ट करें। लॉन्च के बाद वास्तविक मूल्य दिखाई देंगे, लेकिन अब हम किसी भी उपयुक्त व्यक्ति को डालेंगे।

चरण 2। सामग्री नियंत्रक के लिए, निर्दिष्ट Simulated Size
निर्दिष्ट करें। यह पिछले आकार से मेल नहीं खा सकता है।
लेआउट त्रुटियां थीं, मुझे क्या करना चाहिए?त्रुटियाँ तब होती हैं जब AutoLayout
यह पता नहीं लगा सकता है कि वर्तमान आकार में तत्वों को कैसे विघटित किया जाए।
अधिकतर, निरंतरता की प्राथमिकताओं को बदलने के बाद समस्या दूर हो जाती है। आपको उन्हें नीचे रखने की आवश्यकता है ताकि UIView
से एक दूसरों की तुलना में अधिक विस्तार / अनुबंध कर सके।
हम भागों में विभाजित करते हैं और कोड में लिखते हैं
हमने नियंत्रक को कई भागों में विभाजित किया है, लेकिन अभी तक हम उन्हें पुन: उपयोग नहीं कर सकते हैं, UIStoryboard
से इंटरफ़ेस भागों में निकालना मुश्किल है। यदि हमें कुछ डेटा को सामग्री में स्थानांतरित करने की आवश्यकता है, तो हमें पूरी पदानुक्रम के माध्यम से उस पर दस्तक देना होगा। यह चारों ओर का दूसरा तरीका होना चाहिए: पहले सामग्री लें, इसे कॉन्फ़िगर करें, और फिर इसे आवश्यक कंटेनरों में लपेटें। एक बल्ब की तरह।
हमारे रास्ते में तीन कार्य दिखाई देते हैं:
- प्रत्येक नियंत्रक को अपने स्वयं के
UIStoryboard
में अलग करें। container view
मना करें, कोड में कंटेनरों में नियंत्रक जोड़ें।- यह सब वापस बाँधो।
UIStoryboard साझा करना
आपको दो अतिरिक्त UIStoryboard
बनाने और नेविगेशन नियंत्रक और उन में टेम्पलेट नियंत्रक को कॉपी-पेस्ट करने की आवश्यकता है। Embed segue
टूट जाएगा, लेकिन कॉन्फ़िगर की गई बाधाओं के साथ container view
स्थानांतरित हो जाएगा। बाधाओं को बचाया जाना चाहिए, और container view
को नियमित रूप से UIView
से बदला जाना चाहिए।
सबसे आसान तरीका है UIStoryboard कोड में कंटेनर व्यू के प्रकार को बदलना।- एक कोड के रूप में
UIStoryboard
खोलें (फ़ाइल संदर्भ मेनू → के रूप में खोलें ... → स्रोत कोड); containerView
view
से प्रकार बदलें। उद्घाटन और समापन दोनों टैग को बदलना आवश्यक है।
उसी तरह, आप बदल सकते हैं, उदाहरण के लिए, यदि आवश्यक हो तो UIView
से UIScrollView
। और इसके विपरीत।

हम नियंत्रक को संपत्ति पर सेट करते हैं is initial view controller
, और UIStoryboard
नियंत्रक के रूप में UIStoryboard
को कॉल करेंगे।
हम UIStoryboard से कंट्रोलर लोड करते हैं।यदि नियंत्रक का नाम UIStoryboard
के नाम से मेल खाता है, तो डाउनलोड को एक ऐसी विधि में लपेटा जा सकता है जो स्वयं वांछित फ़ाइल को खोज लेगा:
protocol Storyboardable { } extension Storyboardable where Self: UIViewController { static func instantiateInitialFromStoryboard() -> Self { let controller = storyboard().instantiateInitialViewController() return controller! as! Self } static func storyboard(fileName: String? = nil) -> UIStoryboard { let storyboard = UIStoryboard(name: fileName ?? storyboardIdentifier, bundle: nil) return storyboard } static var storyboardIdentifier: String { return String(describing: self) } static var storyboardName: String { return storyboardIdentifier } }
यदि नियंत्रक को .xib
में वर्णित किया गया है, तो मानक निर्माणकर्ता ऐसे नृत्यों के बिना लोड करेगा। काश, .xib
में केवल एक नियंत्रक हो सकता है, अक्सर यह पर्याप्त नहीं होता है: एक अच्छे मामले में, एक स्क्रीन में कई होते हैं। इसलिए, हम UIStoryborad
उपयोग UIStoryborad
, स्क्रीन को भागों में तोड़ना आसान है।
कोड में एक नियंत्रक जोड़ें
नियंत्रक को ठीक से काम करने के लिए, हमें इसके जीवन चक्र के सभी तरीकों की आवश्यकता है: will/did-appear/disappear
।
सही प्रदर्शन के लिए, आपको 5 चरणों को कॉल करने की आवश्यकता है:
willMove(toParent parent: UIViewController?) addChild(_ childController: UIViewController) addSubview(_ subivew: UIView) layout didMove(toParent parent: UIViewController?)
Apple कोड को 4 चरणों में कम करने का सुझाव देता है, क्योंकि willMove(toParent)
addChild()
खुद को willMove(toParent)
। संक्षेप में:
addChild(_ childController: UIViewController) addSubview(_ subivew: UIView) layout didMove(toParent parent: UIViewController?)
सादगी के लिए, आप इसे extension
लपेट सकते हैं। हमारे मामले के लिए, हमें insertSubview()
साथ एक संस्करण की आवश्यकता है।
extension UIViewController { func insertFullframeChildController(_ childController: UIViewController, toView: UIView? = nil, index: Int) { let containerView: UIView = toView ?? view addChild(childController) containerView.insertSubview(childController.view, at: index) containerView.pinToBounds(childController.view) childController.didMove(toParent: self) } }
हटाने के लिए, आपको उसी चरण की आवश्यकता है, केवल मूल नियंत्रक के बजाय आपको nil
सेट करने की आवश्यकता है। अब removeFromParent()
कॉल didMove(toParent: nil)
, और लेआउट की जरूरत नहीं है। छोटा संस्करण बहुत अलग है:
willMove(toParent: nil) view.removeFromSuperview() removeFromParent()
ख़ाका
बाधाओं को सेट करें
नियंत्रक के आकार को सही ढंग से सेट करने के लिए हम AutoLayout
उपयोग करेंगे। हमें सभी पक्षों को सभी पक्षों पर कील लगाने की आवश्यकता है:
extension UIView { func pinToBounds(_ view: UIView) { view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ view.topAnchor.constraint(equalTo: topAnchor), view.bottomAnchor.constraint(equalTo: bottomAnchor), view.leadingAnchor.constraint(equalTo: leadingAnchor), view.trailingAnchor.constraint(equalTo: trailingAnchor) ]) } }
कोड में एक बाल नियंत्रक जोड़ें
अब सब कुछ संयुक्त हो सकता है:
उपयोग की आवृत्ति के कारण, हम यह सब extension
लपेट सकते हैं:
टेम्प्लेट कंट्रोलर के लिए भी इसी तरह की विधि की आवश्यकता होती है। prepare(for segue:)
को prepare(for segue:)
करने के लिए उपयोग किया जाता है prepare(for segue:)
, लेकिन अब आप इसे कंट्रोलर एम्बेड विधि में बांध सकते हैं:
नियंत्रक बनाना इस तरह दिखता है:
टेम्पलेट के लिए एक नई स्क्रीन कनेक्ट करना सरल है:
- सामग्री के लिए प्रासंगिक नहीं है को हटा दें;
- OnboardingViewControllerDatasource प्रोटोकॉल लागू करके कार्रवाई बटन निर्दिष्ट करें;
- एक विधि लिखें जो एक टेम्पलेट और सामग्री को जोड़ता है।
कंटेनरों के बारे में अधिक
स्थिति पट्टी
कन्टैंट status bar
कंट्रोल करने के लिए status bar
की दृश्यता के लिए यह आवश्यक होता है कि कन्टेनर नहीं। इसके लिए property
का एक जोड़ा है:
इन property
का उपयोग करके property
आप नियंत्रकों की एक श्रृंखला बना सकते हैं, बाद वाली status bar
प्रदर्शित करने के लिए जिम्मेदार होगी।
सुरक्षित क्षेत्र
यदि कंटेनर बटन सामग्री को ओवरलैप करते हैं, तो आपको safeArea
क्षेत्र को बढ़ाना चाहिए। यह कोड में किया जा सकता है: बाल नियंत्रकों के लिए additinalSafeAreaInsets
सेट करें। आप इसे embedController()
से embedController()
:
private func addSafeArea(to controller: UIViewController) { if #available(iOS 11.0, *) { let buttonHeight = CGFloat(30) let topInset = UIEdgeInsets(top: buttonHeight, left: 0, bottom: 0, right: 0) controller.additionalSafeAreaInsets = topInset } }
यदि आप शीर्ष पर 30 अंक जोड़ते हैं, तो बटन अतिव्यापी सामग्री को रोक देगा और safeArea
हरे क्षेत्र पर कब्जा कर safeArea
:

हाशिये। सुपरवाइज मार्जिन को संरक्षित करें
नियंत्रकों में मानक margins
। आमतौर पर वे स्क्रीन के प्रत्येक पक्ष से 16 अंक के बराबर होते हैं और केवल प्लस-आकार पर वे 20 अंक होते हैं।
margins
आधार पर margins
आप स्थिरांक बना सकते हैं, अलग-अलग iPhones के लिए किनारे पर इंडेंटेशन अलग होगा:

जब हम एक UIView
को दूसरे में रखते हैं, तो margins
आधा कर दिया जाता है: 8 अंक। इसे रोकने के लिए, आपको Preserve superview margins
को शामिल करने की आवश्यकता है। फिर बच्चे का margins
UIView
माता-पिता के margins
बराबर होगा। यह पूर्ण स्क्रीन कंटेनरों के लिए उपयुक्त है।
अंत
कंटेनर नियंत्रक एक शक्तिशाली उपकरण हैं। वे कोड को सरल करते हैं, अलग कार्य करते हैं, और उनका पुन: उपयोग किया जा सकता है। आप किसी भी तरह से नेस्टेड कंट्रोलर लिख सकते हैं: UIStoryboard
, .xib
या कोड में। सबसे महत्वपूर्ण बात, वे बनाने में आसान और उपयोग करने में मज़ेदार हैं।
→ GitHub पर एक लेख से एक उदाहरण
क्या आपके पास ऐसी स्क्रीन हैं जिनसे यह एक टेम्प्लेट बनाने लायक होगा? टिप्पणियों में साझा करें!