यह रेखा:
[self dismissViewControllerAnimated:YES completion:nil];
अपने आप को एक संदेश नहीं भेज रहा है, यह वास्तव में अपने वर्तमान वीसी को एक संदेश भेज रहा है, इसे खारिज करने के लिए कह रहा है। जब आप एक वीसी प्रस्तुत करते हैं, तो आप वर्तमान वीसी और प्रस्तुत एक के बीच संबंध बनाते हैं। इसलिए आपको प्रस्तुत करते समय उपस्थित वीसी को नष्ट नहीं करना चाहिए (प्रस्तुत वीसी उस बर्खास्त संदेश को वापस नहीं भेज सकता ...)। जैसा कि आप वास्तव में इसका हिसाब नहीं ले रहे हैं, आप ऐप को असमंजस की स्थिति में छोड़ रहे हैं। मेरा जवाब देखें एक प्रस्तुत दृश्य नियंत्रक को खारिज करना
जिसमें मैं यह सलाह देता हूं कि यह विधि अधिक स्पष्ट रूप से लिखी गई है:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
आपके मामले में, आपको यह सुनिश्चित करने की आवश्यकता है कि सभी नियंत्रण में किया जाता है mainVC
। आपको ViewController1 से MainViewController को सही संदेश भेजने के लिए एक प्रतिनिधि का उपयोग करना चाहिए, ताकि MainVC VC1 को खारिज कर सके और फिर VC2 पेश कर सके।
में VC2 VC1 @interface ऊपर अपने ज फ़ाइल में एक प्रोटोकॉल जोड़ें:
@protocol ViewController1Protocol <NSObject>
- (void)dismissAndPresentVC2;
@end
और @interface अनुभाग में एक ही फाइल में नीचे प्रतिनिधि प्रतिनिधि रखने के लिए एक संपत्ति की घोषणा:
@property (nonatomic,weak) id <ViewController1Protocol> delegate;
VC1 .m फ़ाइल में, बर्खास्त बटन विधि को प्रतिनिधि विधि को कॉल करना चाहिए
- (IBAction)buttonPressedFromVC1:(UIButton *)sender {
[self.delegate dissmissAndPresentVC2]
}
अब mainVC में, VC1 बनाते समय इसे VC1 के प्रतिनिधि के रूप में सेट करें:
- (IBAction)present1:(id)sender {
ViewController1* vc = [[ViewController1 alloc] initWithNibName:@"ViewController1" bundle:nil];
vc.delegate = self;
[self present:vc];
}
और प्रतिनिधि विधि को लागू करें:
- (void)dismissAndPresent2 {
[self dismissViewControllerAnimated:NO completion:^{
[self present2:nil];
}];
}
present2:
अपने VC2Pressed:
बटन IBAction विधि के समान विधि हो सकती है । ध्यान दें कि यह पूर्णता ब्लॉक से यह सुनिश्चित करने के लिए कहा जाता है कि VC2 को तब तक प्रस्तुत नहीं किया जाता है जब तक कि VC1 को पूरी तरह से खारिज नहीं किया जाता है।
अब आप VC1-> VCMain-> VC2 से आगे बढ़ रहे हैं, इसलिए आप शायद केवल एक बदलाव को एनिमेटेड बनाना चाहेंगे।
अपडेट करें
अपनी टिप्पणियों में आप एक साधारण सी बात को प्राप्त करने के लिए आवश्यक जटिलता पर आश्चर्य व्यक्त करते हैं। मैं आपको विश्वास दिलाता हूं, यह प्रतिनिधि पैटर्न बहुत उद्देश्य-सी और कोको के लिए केंद्रीय है, और यह उदाहरण आपको प्राप्त होने वाले सबसे सरल के बारे में है, कि आपको वास्तव में इसके साथ सहज होने का प्रयास करना चाहिए।
Apple के व्यू कंट्रोलर प्रोग्रामिंग गाइड में उनके पास यह कहने के लिए है :
प्रस्तुत दृश्य नियंत्रक को खारिज करना
जब यह एक प्रस्तुत दृश्य नियंत्रक को खारिज करने का समय आता है, तो पसंदीदा दृष्टिकोण प्रस्तुतकर्ता नियंत्रक को इसे खारिज करने देता है। दूसरे शब्दों में, जब भी संभव हो, दृश्य नियंत्रक को प्रस्तुत करने वाला वही दृश्य नियंत्रक को इसे खारिज करने की जिम्मेदारी भी लेनी चाहिए। यद्यपि प्रस्तुत दृश्य नियंत्रक को सूचित करने के लिए कई तकनीकें हैं कि उसके प्रस्तुत दृश्य नियंत्रक को खारिज कर दिया जाना चाहिए, पसंदीदा तकनीक प्रतिनिधि है। अधिक जानकारी के लिए, "अन्य नियंत्रकों के साथ संवाद करने के लिए प्रतिनिधि का उपयोग करना" देखें।
यदि आप वास्तव में सोचते हैं कि आप क्या हासिल करना चाहते हैं, और आप इसके बारे में कैसे जा रहे हैं, तो आप महसूस करेंगे कि अपने मेनव्यूकंट्रोलर को सभी काम करने के लिए संदेश देना केवल तार्किक तरीका है जिसे आप एक नेविगेशनकंट्रोलर का उपयोग नहीं करना चाहते हैं। यदि आप एक NavController का उपयोग करते हैं, तो वास्तव में आप 'डेलिगेट' कर रहे हैं, भले ही स्पष्ट रूप से, NavController को सभी काम करने के लिए नहीं। कुछ ऐसी वस्तुएं होनी चाहिए जो आपके वीसी नेविगेशन के साथ क्या हो रहा है, का एक केंद्रीय ट्रैक रखता है, और आपको इसके साथ संवाद करने की कुछ विधि की आवश्यकता है, जो भी आप करते हैं।
व्यवहार में, Apple की सलाह थोड़ी चरम है ... सामान्य मामलों में, आपको एक समर्पित प्रतिनिधि और विधि बनाने की आवश्यकता नहीं है, आप इस पर भरोसा कर सकते हैं [self presentingViewController] dismissViewControllerAnimated:
- यह आपके जैसे मामलों में है जब आप चाहते हैं कि आपके बर्खास्तगी का रिमोट पर अन्य प्रभाव हो। जिन वस्तुओं की आपको देखभाल करने की आवश्यकता है।
यहाँ कुछ ऐसा है जिसे आप सभी प्रतिनिधि परेशानी के बिना काम करने की कल्पना कर सकते हैं ...
- (IBAction)dismiss:(id)sender {
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:^{
[self.presentingViewController performSelector:@selector(presentVC2:)
withObject:nil];
}];
}
हमें खारिज करने के लिए प्रस्तुत करने वाले नियंत्रक से पूछने के बाद, हमारे पास एक पूर्ण ब्लॉक है जो VC2 को आमंत्रित करने के लिए presentingViewController में एक विधि कहता है। किसी प्रतिनिधि की जरूरत नहीं। (ब्लॉक का एक बड़ा विक्रय बिंदु यह है कि वे इन परिस्थितियों में प्रतिनिधियों की आवश्यकता को कम कर देते हैं)। हालाँकि इस मामले में कुछ चीजें हो रही हैं ...
- VC1 में आप नहीं जानते कि mainVC विधि को लागू करता है
present2
- आप कठिन-से-डीबग त्रुटियों या क्रैश के साथ समाप्त हो सकते हैं। इससे बचने के लिए प्रतिनिधि आपकी मदद करते हैं।
- एक बार जब VC1 खारिज कर दिया जाता है, तो यह वास्तव में पूर्ण ब्लॉक को निष्पादित करने के आसपास नहीं है ... या यह है? क्या Self.pretingViewController का मतलब कुछ और है? आप नहीं जानते (न ही मैं) ... एक प्रतिनिधि के साथ, आपके पास यह अनिश्चितता नहीं है।
- जब मैं इस विधि को चलाने की कोशिश करता हूं, तो यह बिना किसी चेतावनी या त्रुटियों के साथ लटका रहता है।
तो कृपया ... प्रतिनिधिमंडल सीखने के लिए समय निकालें!
Update2
अपनी टिप्पणी में आपने VC2 के बर्खास्त बटन हैंडलर में इसका उपयोग करके इसे बनाने में कामयाबी हासिल की है:
[self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
यह निश्चित रूप से बहुत सरल है, लेकिन यह आपको कई मुद्दों के साथ छोड़ देता है।
तंग युग्मन
आप हार्ड-वायरिंग कर रहे हैं अपने दृश्य संरचना एक साथ। उदाहरण के लिए, यदि आप mainVC से पहले एक नया viewController डालें, तो आपका आवश्यक व्यवहार टूट जाएगा (आप पहले वाले पर नेविगेट करेंगे)। VC1 में आपको #import VC2 भी देना होता है। इसलिए आपके पास बहुत अधिक अंतर-निर्भरताएं हैं, जो ओओपी / एमवीसी उद्देश्यों को तोड़ती हैं।
प्रतिनिधियों का उपयोग करते हुए, न तो VC1 और न ही VC2 को mainVC के बारे में कुछ भी जानने की जरूरत है या यह एंटीकेडेंट्स हैं, इसलिए हम सब कुछ शिथिल-युग्मित और मॉड्यूलर रखते हैं।
याद
VC1 दूर नहीं गया है, आप अभी भी इसे दो संकेत देते हैं:
- mainVC के
presentedViewController
संपत्ति
- VC2 के
presentingViewController
संपत्ति
आप इसे लॉग इन करके टेस्ट कर सकते हैं और वो भी सिर्फ VC2 से ऐसा करके
[self dismissViewControllerAnimated:YES completion:nil];
यह अभी भी काम करता है, फिर भी आपको VC1 पर वापस ले जाता है।
वह मुझे स्मृति रिसाव की तरह लगता है।
इसका सुराग आपको यहां मिल रही चेतावनी में है:
[self presentViewController:vc2 animated:YES completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
तर्क टूट जाता है, जैसा कि आप प्रस्तुत करने वाले कुलपति को खारिज करने का प्रयास कर रहे हैं जिसमें से VC2 प्रस्तुत कुलपति है। दूसरा संदेश वास्तव में निष्पादित नहीं होता है - अच्छी तरह से शायद कुछ सामान होता है, लेकिन आप अभी भी दो पॉइंटर्स के साथ एक ऑब्जेक्ट पर छोड़ दिए जाते हैं जिसे आपने सोचा था कि आपको छुटकारा मिल गया है। ( संपादित करें - मैंने इसकी जाँच कर ली है और यह इतना बुरा नहीं है, जब आप mainVC में वापस आते हैं तो दोनों वस्तुएं चली जाती हैं )
यह कहने का लंबा-चौड़ा तरीका है - कृपया, प्रतिनिधियों का उपयोग करें। यदि यह मदद करता है, तो मैंने यहां पैटर्न का एक और संक्षिप्त विवरण दिया है:
क्या एक कसौटी में नियंत्रक हमेशा खराब अभ्यास है?
अद्यतन 3
यदि आप वास्तव में प्रतिनिधियों से बचना चाहते हैं, तो यह सबसे अच्छा तरीका हो सकता है:
VC1 में:
[self presentViewController:VC2
animated:YES
completion:nil];
लेकिन नहीं कुछ भी खारिज ... जैसा कि हमने जाना, यह वास्तव में वैसे भी नहीं होता है।
VC2 में:
[self.presentingViewController.presentingViewController
dismissViewControllerAnimated:YES
completion:nil];
हम (पता) हम VC1 ख़ारिज नहीं किया है के रूप में, हम वापस तक पहुँच सकते हैं के माध्यम से VC1 को MainVC। MainVC VC1 को खारिज करता है। क्योंकि VC1 चला गया है, इसे प्रस्तुत किया गया है VC2 इसके साथ जाता है, इसलिए आप स्वच्छ स्थिति में MainVC में वापस आ गए हैं।
यह अभी भी बहुत अधिक युग्मित है, क्योंकि VC1 को VC2 के बारे में जानने की आवश्यकता है, और VC2 को यह जानने की आवश्यकता है कि यह MainVC-> VC1 के माध्यम से आया था, लेकिन यह सबसे अच्छा है जो आप बिना स्पष्ट प्रतिनिधिमंडल के प्राप्त करेंगे।