AddChildViewController वास्तव में क्या करता है?


102

मैं सिर्फ iOS विकास में पहली बार अपने पैरों को डुबो रहा हूं, और मुझे जो पहली चीज करनी है, वह कस्टम कंटेनर व्यू कंट्रोलर को लागू करना है - इसे कॉल करने देता है SideBarViewController- जो कई संभावित चाइल्ड व्यू कंट्रोलरों में से इसे स्वैप करता है दिखाता है, लगभग एक मानक टैब बार नियंत्रक की तरह । (यह एक टैब बार नियंत्रक की तुलना में बहुत अधिक है, लेकिन टैब बार के बजाय छिपने योग्य साइड मेनू के साथ है।)

Apple दस्तावेज़ीकरण के निर्देशों के अनुसार, addChildViewControllerजब भी मैं अपने कंटेनर में एक बच्चा ViewController जोड़ता हूं , तो मैं कॉल करता हूं। वर्तमान बाल दृश्य नियंत्रक को स्वैप करने के लिए मेरा कोड SideBarViewControllerइस तरह दिखता है:

- (void)showViewController:(UIViewController *)newViewController {
    UIViewController* oldViewController = [self.childViewControllers 
                                           objectAtIndex:0];
    
    [oldViewController removeFromParentViewController];
    [oldViewController.view removeFromSuperview];
    
    newViewController.view.frame = CGRectMake(
        0, 0, self.view.frame.size.width, self.view.frame.size.height
    );
    [self addChildViewController: newViewController];
    [self.view addSubview: newViewController.view];
}

तब मैंने यह पता लगाने की कोशिश शुरू कर दी कि addChildViewControllerयहाँ क्या होता है, और मुझे एहसास हुआ कि मुझे कोई पता नहीं है। सरणी ViewControllerमें नए को चिपकाने के अलावा .childViewControllers, इसका किसी भी चीज पर कोई प्रभाव नहीं पड़ता है। चाइल्ड कंट्रोलर के दृश्य से लेकर चाइल्ड कंट्रोलर तक के एक्ट्स और आउटलेट्स, जो मैंने स्टोरीबोर्ड पर सेट किए हैं, अभी भी ठीक काम करते हैं, भले ही मैंने कभी फोन न किया हो addChildViewController, और मैं कल्पना नहीं कर सकता कि यह और क्या प्रभावित कर सकता है।

वास्तव में, यदि मैं अपने कोड को फिर से न बुलाने के लिए लिखूं addChildViewController, और इसके बजाय इस तरह दिखना चाहिए ...

- (void)showViewController:(UIViewController *)newViewController {

    // Get the current child from a member variable of `SideBarViewController`
    UIViewController* oldViewController = currentChildViewController;

    [oldViewController.view removeFromSuperview];

    newViewController.view.frame = CGRectMake(
        0, 0, self.view.frame.size.width, self.view.frame.size.height
    );
    [self.view addSubview: newViewController.view];

    currentChildViewController = newViewController;
}

... तो मेरा ऐप अभी भी पूरी तरह से काम करता है, जहाँ तक मैं बता सकता हूँ!

Apple प्रलेखन क्या addChildViewControllerकरता है, या हम इसे क्यों कहते हैं, इस पर बहुत प्रकाश नहीं डालते हैं। वर्तमान में UIViewControllerक्लास रेफरेंस में इसके सेक्शन में क्या किया जाता है या क्यों इस्तेमाल किया जाना चाहिए, इसके प्रासंगिक विवरण की पूरी सीमा इस प्रकार है :

दिए गए दृश्य नियंत्रक को एक बच्चे के रूप में जोड़ता है। ... इस विधि को केवल एक कस्टम कंटेनर व्यू कंट्रोलर के कार्यान्वयन द्वारा बुलाया जाना है। यदि आप इस विधि को ओवरराइड करते हैं, तो आपको अपने कार्यान्वयन में सुपर कॉल करना होगा।

उसी पृष्ठ पर पहले भी यह अनुच्छेद है:

आपके कंटेनर व्यू कंट्रोलर को बच्चे के रूट दृश्य को पदानुक्रम में जोड़ने से पहले एक चाइल्ड व्यू कंट्रोलर को अपने साथ जोड़ना होगा। यह iOS को चाइल्ड व्यू कंट्रोलर्स और उन नियंत्रकों को प्रबंधित करने वाले विचारों को ठीक से रूट करने की अनुमति देता है। इसी तरह, यह अपने दृश्य पदानुक्रम से एक बच्चे के मूल दृश्य को हटाने के बाद, उसे स्वयं से उस बच्चे के दृश्य नियंत्रक को डिस्कनेक्ट करना चाहिए। इन संघों को बनाने या तोड़ने के लिए, आपका कंटेनर बेस क्लास द्वारा परिभाषित विशिष्ट तरीकों को कॉल करता है। इन विधियों का उद्देश्य आपके कंटेनर वर्ग के ग्राहकों द्वारा बुलाया जाना नहीं है; अपेक्षित कंटेंट व्यवहार प्रदान करने के लिए उन्हें केवल आपके कंटेनर के कार्यान्वयन द्वारा उपयोग किया जाना है।

यहाँ आवश्यक तरीके हैं जिन्हें आपको कॉल करने की आवश्यकता हो सकती है:


AddChildViewController : removeFromParentViewController
willMoveToParentViewController:
didMoveToParentViewController:

लेकिन यह इस बात की पेशकश नहीं करता है कि 'ईवेंट्स' या 'अपेक्षित कंटेंट बिहेवियर' क्या है जिसके बारे में यह बात कर रहा है या क्यों (या तब भी) जब इन तरीकों को कॉल करना 'आवश्यक' है।

Apple डॉक्यूमेंट के "कस्टम कंटेनर व्यू कंट्रोलर्स" सेक्शन में कस्टम कंटेनर व्यू कंट्रोलर्स के उदाहरण सभी इस विधि को कहते हैं, इसलिए मेरा मानना ​​है कि यह कुछ महत्वपूर्ण उद्देश्य से परे है जो कि बच्चे को व्यूऑनलाइनर व्यूअर को पॉपअप करने से परे है, लेकिन मैं समझ नहीं पा रहा हूं वह उद्देश्य क्या है। यह विधि क्या करती है, और मुझे इसे क्यों कॉल करना चाहिए?


3
इस विषय पर Apple के 2011 के WWDC वीडियो पेज का एक शानदार सत्र ("यूआईवीवाईकंट्रोलर कंटेनर लागू करना") है।
अल्लादीन

जवाबों:


94

मैं इस सवाल के बारे में भी सोच रहा था। मैंने WWDC 2011 के वीडियो और श्री व्यू कंट्रोलर, ब्रूस डी। निलो के सत्र 102 को देखा , यह कहा:

viewWillAppear:, viewDidAppear:आदि का कोई लेना-देना नहीं है addChildViewController:। यह सब addChildViewController:कहना है "यह दृश्य नियंत्रक उस एक का बच्चा है" और इसका दृश्य उपस्थिति से कोई लेना-देना नहीं है। जब उन्हें बुलाया जाता है, जब विंडो पदानुक्रम में अंदर और बाहर जाने के दृश्य जुड़े होते हैं।

तो ऐसा लगता है कि कॉल addChildViewController:बहुत कम करता है। कॉल के साइड इफेक्ट्स महत्वपूर्ण हिस्सा हैं। वे से आते हैं parentViewControllerऔर childViewControllersरिश्ते। यहाँ कुछ दुष्प्रभाव हैं जो मुझे पता हैं:

  • बच्चे को देखने वाले नियंत्रकों के लिए उपस्थिति विधियों को अग्रेषित करना
  • अग्रेषण रोटेशन के तरीके
  • (संभवतः) स्मृति चेतावनी को अग्रेषित करना
  • असंगत वीसी पदानुक्रम से बचना, विशेष रूप से अंदर transitionFromViewController:toViewController:… जहां दोनों कुलपतियों को एक ही माता-पिता की आवश्यकता होती है
  • राज्य संरक्षण और बहाली में भाग लेने के लिए कस्टम कंटेनर दृश्य नियंत्रकों की अनुमति देना
  • उत्तरदाता श्रृंखला में भाग लेना
  • ऊपर hooking navigationController, tabBarController, आदि गुण

यह सत्र 102 नहीं 101
सीनचेन

उत्तरदाता श्रृंखला के लिए +1। addChildViewController की आवश्यकता है यदि आप एक बच्चे के स्वामित्व वाले उप
दृश्य

108

मुझे लगता है कि एक उदाहरण एक हजार शब्दों के लायक है।

मैं एक लाइब्रेरी ऐप पर काम कर रहा था और एक अच्छा नोटपैड दृश्य दिखाना चाहता था जो तब दिखाई देता है जब उपयोगकर्ता एक नोट जोड़ना चाहता है।

यहां छवि विवरण दर्ज करें

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

तब मैंने देखा कि नोटपैड की छवि आंशिक रूप से लैंडस्केप मोड में कीबोर्ड के नीचे छिपी हुई है।

यहां छवि विवरण दर्ज करें

इसलिए मैं नोटपैड की छवि को बदलना चाहता था और इसे स्थानांतरित करना चाहता था। और ऐसा करने के लिए, मैंने willAnimateRotationToInterfaceOrientation:duration:विधि में उचित कोड लिखा , लेकिन जब मैंने ऐप चलाया तो कुछ नहीं हुआ! और डिबगिंग के बाद मैंने देखा कि UIViewControllerवास्तव में रोटेशन विधियों में से कोई भी नहीं कहा जाता हैNotepadViewController । मुख्य दृश्य नियंत्रक में केवल उन विधियों को बुलाया जा रहा है।

इसे हल करने के लिए, मुझे सभी विधियों को कॉल करने की आवश्यकता है NotepadViewController मुख्य दृश्य नियंत्रक में बुलाया जाता है मैन्युअल रूप । यह जल्द ही चीजों को जटिल बना देगा और ऐप में असंबंधित घटकों के बीच एक अतिरिक्त निर्भरता पैदा करेगा।

इससे पहले, चाइल्ड व्यू कंट्रोलर्स की अवधारणा को पेश किए जाने से पहले था। लेकिन अब, आपको केवल addChildViewControllerमुख्य दृश्य नियंत्रक की आवश्यकता है और सब कुछ बस किसी भी अधिक मैनुअल काम के बिना अपेक्षित होगा।

संपादित करें: घटनाओं की दो श्रेणियां हैं जो बाल दृश्य नियंत्रकों को अग्रेषित की जाती हैं:

1 - सूरत तरीके:

- viewWillAppear:
- viewDidAppear:
- viewWillDisappear:
- viewDidDisappear:

2- रोटेशन के तरीके:

- willRotateToInterfaceOrientation:duration:
- willAnimateRotationToInterfaceOrientation:duration:
- didRotateFromInterfaceOrientation:

आप यह भी नियंत्रित कर सकते हैं कि आप कौन सी ईवेंट श्रेणियों को ओवरराइड करके shouldAutomaticallyForwardRotationMethodsऔर स्वचालित रूप से अग्रेषित करना चाहते हैं shouldAutomaticallyForwardAppearanceMethods


दस्तावेज़ीकरण से और एक त्वरित परीक्षण करने के बाद मुझे नहीं लगता कि कोई अन्य घटना है जो केवल अगर आप addChildViewControllerमूल नियंत्रक के लिए अग्रेषित की जाती है ।
हिजाज़ी

काश यह स्वचालित रूप से अग्रेषित किया गया दृश्यविलायआउट साक्षात्कार
MobileMon

10

-[UIViewController addChildViewController:]केवल व्यू कंट्रोलर की एक सरणी में व्यू कंट्रोलर में पास किया गया है जो एक व्यू कॉन्ट्रोलर (माता-पिता) के संदर्भ को रखना चाहता है। आपको वास्तव में स्क्रीन पर उन व्यू-कॉन्ट्रॉलर के विचारों को जोड़ना चाहिए, उन्हें एक अन्य दृश्य (जैसे पेरेंटव्यूकंट्रोलर के दृश्य) के एक साक्षात्कार के रूप में जोड़कर। स्टोरीबोर्ड में चिल्ड्रन व्यू कॉन्ट्रोलर्स का उपयोग करने के लिए इंटरफ़ेस बिल्डर में एक सुविधा ऑब्जेक्ट भी है।

इससे पहले, अन्य दृश्य के संदर्भों को रखने के लिए जिनमें से आपने विचारों का उपयोग किया था, आपको @properties में उनमें से मैनुअल संदर्भ रखना होगा। बिल्ट -इन प्रॉपर्टी की तरह होना childViewControllersऔर फलस्वरूप parentViewControllerइस तरह के इंटरैक्शन को मैनेज करना और यूआईप्लिसटिव व्यूकंट्रोलर जैसे कंपोज़्ड व्यू कॉन्ट्रोलर्स को बनाना एक सुविधाजनक तरीका है जो आपको आईपैड ऐप्स पर मिलता है।

इसके अलावा, ChildrenViewControllers भी स्वचालित रूप से उन सभी सिस्टम ईवेंट को प्राप्त करते हैं जो माता-पिता को प्राप्त होते हैं: -viewWillAppear, -viewWillDisappear, आदि। पहले आपको अपने "childrenViewControllers" पर मैन्युअल रूप से इस तरीके को कॉल करना चाहिए।

बस।


आपके सोचने का आधार क्या है कि यह सब करता है? इसके अलावा, क्या आप बच्चे को मिलने वाली 'सिस्टम ईवेंट' की सूची प्रदान कर सकते हैं? एक Google खोज iOS "system events"बहुत ऊपर नहीं फेंकती है; ऐसा प्रतीत नहीं होता है कि Apple एक शब्द का उपयोग करता है?
मार्क अमेरी

यह मूल रूप से एक सुविधा पद्धति है, जो आपको व्यू कंट्रोलर बी के व्यू को व्यू कंट्रोलर ए के उप-भाग के रूप में जोड़ने की अनुमति देती है, लेकिन फिर भी व्यू कंट्रोलर बी को अपने व्यू को मैनेज करने की सुविधा है। इसे ठीक से काम करने के लिए, आपको यह सुनिश्चित करने की आवश्यकता है कि व्यू कंट्रोलर बी को सिस्टम ईवेंट मिल रहा है (UIViewControllerDelegate कॉलबैक पढ़ें)। 'addChildViewController' आपके लिए यह सबकुछ निर्धारित करता है, ताकि आप मैन्युअल रूप से सब कुछ पास करने के प्रयास को बचा सकें।
सैम क्लेव्लो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.