दिलचस्प पोस्ट
जब मैं javax.tools.javaCompiler का उपयोग करता हूँ, तब वर्गपथ को कैसे सेट किया जाए? मैं दशमलव के रूप में एक इंट क्यों नहीं खुल सकता? मॉडल्स की सूची के लिए रिमोट मान्यता जावास्क्रिप्ट में एकाधिक असाइनमेंट? = क्या करता है; क्या मतलब है? क्या जावा में कंस्ट्रक्टर कोड चलाने से पहले खेले जाने वाले फ़ील्ड शुरू होते हैं? एसडी कार्ड से बिटमैप में एक छवि फ़ाइल को पढ़ना, मुझे एक NullPointerException क्यों मिल रहा है? क्या मैं jQuery का उपयोग कर एक ड्रॉपडाउन सूची खोल सकता हूं? मैवेन: कस्टम प्रोजेक्ट जार को जोड़ने के सर्वोत्तम तरीके से मेरी परियोजना? अजगर में सत्य और फाल्सी क्या है? यह कैसे सच और गलत से अलग है? पीडीओ में पीडीओ के साथ खोले गए एसक्यूएल कनेक्शन को बंद करना होगा सी + + मॉड्यूल – उन्हें सी ++ 0x से क्यों हटा दिया गया? क्या वे बाद में वापस आ जाएंगे? PHP पृष्ठभूमि प्रक्रियाएं एक ही पंक्ति पर गूंज कैसे दिखाना और अपडेट करना AppCompat v7 r21 values.xml में त्रुटि लौट रहा है? मैं कैसे जाँच सकता हूँ कि एक सरणी php में एक विशिष्ट मान है?

मोडल व्यू नियंत्रक – प्रदर्शित करने और खारिज करने का तरीका

मैं पिछले एक हफ्ते से अपने सिर को तोड़ रहा हूं कि कैसे कई दृश्य नियंत्रकों को दिखाना और खारिज करने के मुद्दे को हल करना है मैंने एक नमूना प्रोजेक्ट बनाया है और परियोजना से सीधे कोड चिपकाया है। मेरे पास 3 दृश्य नियंत्रक हैं जो उनके संबंधित .xib फ़ाइलों के साथ हैं मुख्य दृश्य नियंत्रक, वीसी 1 और वीसी 2 मुख्य दृश्य नियंत्रक पर मेरे पास दो बटन हैं I

- (IBAction)VC1Pressed:(UIButton *)sender { VC1 *vc1 = [[VC1 alloc] initWithNibName:@"VC1" bundle:nil]; [vc1 setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal]; [self presentViewController:vc1 animated:YES completion:nil]; } 

यह कोई मुद्दों के साथ वीसी 1 खोलता है वीसी 1 में, मेरे पास एक और बटन है, जिसे वीसी 2 खोलना चाहिए, जबकि उसी समय वीसी 1 को खारिज करना चाहिए।

 - (IBAction)buttonPressedFromVC1:(UIButton *)sender { VC2 *vc2 = [[VC2 alloc] initWithNibName:@"VC2" bundle:nil]; [vc2 setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal]; [self presentViewController:vc2 animated:YES completion:nil]; [self dismissViewControllerAnimated:YES completion:nil]; } // This shows a warning: Attempt to dismiss from view controller <VC1: 0x715e460> while a presentation or dismiss is in progress! - (IBAction)buttonPressedFromVC2:(UIButton *)sender { [self dismissViewControllerAnimated:YES completion:nil]; } // This is going back to VC1. 

मैं चाहता हूं कि वह मुख्य दृश्य नियंत्रक पर वापस जाए, जबकि एक ही समय में वीसी 1 को स्मृति से अच्छे से हटा दिया जाना चाहिए था VC1 केवल तब दिखाना चाहिए जब मैं मुख्य नियंत्रक पर VC1 बटन पर क्लिक करता हूं।

मेन व्यू नियंत्रक के दूसरे बटन को वीसी 2 सीधे वीसी 1 को बायपास करने में सक्षम होना चाहिए और जब वीसी 2 पर एक बटन क्लिक किया जाए तो मुख्य नियंत्रक को वापस आ जाना चाहिए। कोई लंबे समय से चलने वाला कोड, छोरों या किसी भी टाइमर नहीं है कंट्रोलर को देखने के लिए बस बेअर हंस कॉल

वेब के समाधान से एकत्रित समाधान "मोडल व्यू नियंत्रक – प्रदर्शित करने और खारिज करने का तरीका"

यह रेखा:

 [self dismissViewControllerAnimated:YES completion:nil]; 

अपने आप को कोई संदेश नहीं भेज रहा है, यह वास्तव में अपने वर्तमान वीसी को एक संदेश भेज रहा है, जिससे वह खारिज करने के लिए कह रहा है जब आप एक उपकुलपति पेश करते हैं, तो आप प्रस्तुति कुलपति और प्रस्तुत एक के बीच संबंध बनाते हैं। इसलिए प्रस्तुत करने के दौरान पेश करने वाले विजिट को आप को नहीं तोड़ना चाहिए (प्रस्तुत वीसी वे संदेश भेज सकते हैं जो संदेश वापस खारिज कर देते हैं …) जैसा कि आप वास्तव में इसका खाता नहीं ले रहे हैं, आप एप को एक भ्रमित स्थिति में छोड़ रहे हैं। मेरा उत्तर देखें एक प्रस्तुत दृश्य नियंत्रक को अस्वीकार करना जिसमें मैं सुझाता हूं कि यह विधि अधिक स्पष्ट रूप से लिखा गया है:

 [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 

आपके मामले में, आपको यह सुनिश्चित करना होगा कि मुख्य नियंत्रण में सभी नियंत्रण किया गया है। आपको ViewController1 से सही संदेश वापस MainViewController पर भेजने के लिए एक प्रतिनिधि का उपयोग करना चाहिए, ताकि मुख्यवीसी VC1 और उसके बाद वर्तमान VC2 को खारिज कर सके।

VC2 VC1 में @interface के ऊपर आपकी .h फ़ाइल में एक प्रोटोकॉल जोड़ें:

 @protocol ViewController1Protocol <NSObject> - (void)dismissAndPresentVC2; @end 

और @ इंटरफेस अनुभाग में एक ही फ़ाइल में कम नीचे प्रतिनिधि गुणक को पकड़ने के लिए संपत्ति घोषित करें:

 @property (nonatomic,weak) id <ViewController1Protocol> delegate; 

वीसी 1। मी फ़ाइल में, खारिज बटन विधि को प्रतिनिधि विधि को कॉल करना चाहिए

 - (IBAction)buttonPressedFromVC1:(UIButton *)sender { [self.delegate dissmissAndPresentVC2] } 

अब मुख्यवीसी में, वीसी 1 के निर्माण करते समय इसे वीसी 1 के प्रतिनिधि के रूप में सेट करें:

 - (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: रूप में एक ही विधि हो सकती है VC2Pressed: बटन IBAction विधि ध्यान दें कि इसे पूर्णतया ब्लॉक से कहा गया है कि VC1 पूरी तरह से खारिज होने तक वीसी 2 प्रस्तुत नहीं किया गया है।

अब आप VC1-> VCMain-> VC2 से आगे बढ़ रहे हैं, इसलिए आप संभवत: एनिमेटेड होने वाले बदलावों में से केवल एक ही चाहते हैं।

अद्यतन करें

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

ऐप्पल के व्यू नियंत्रक प्रोग्रामिंग गाइड में उनका यह कहना है :

एक प्रस्तुत दृश्य नियंत्रक को अस्वीकार करना

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

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

अभ्यास में एप्पल की सलाह थोड़ी सी चरम है … सामान्य मामलों में, आपको एक समर्पित प्रतिनिधि और विधि बनाने की ज़रूरत नहीं है, आप [self presentingViewController] dismissViewControllerAnimated: कर सकते हैं [self presentingViewController] dismissViewControllerAnimated: – जब यह आपके जैसे मामलों में होता है जिसे आप अपनी बर्खास्तगी चाहते हैं रिमोट ऑब्जेक्ट्स पर अन्य प्रभाव रखने के लिए जिन्हें आपको ध्यान रखना चाहिए।

यहां कुछ ऐसी चीजें हैं जो आप सभी प्रतिनिधि परेशानियों के बिना काम करने की कल्पना कर सकते हैं

 - (IBAction)dismiss:(id)sender { [[self presentingViewController] dismissViewControllerAnimated:YES completion:^{ [self.presentingViewController performSelector:@selector(presentVC2:) withObject:nil]; }]; } 

हमें डिसप्ले करने के लिए प्रस्तुतकर्ता नियंत्रक से पूछने के बाद, हमारे पास एक पूरा ब्लॉक है जो वर्तमान VVV नियंत्रक में एक विधि कॉल करता है जो कि वीसी 2 को आमंत्रित करता है। कोई प्रतिनिधि की जरूरत नहीं है (ब्लॉक का एक बड़ा विक्रय बिंदु है कि वे इन परिस्थितियों में प्रतिनिधियों की आवश्यकता को कम करते हैं)। हालांकि इस मामले में रास्ते में कुछ चीजें मिल रही हैं …

  • वीसी 1 में आप नहीं जानते कि मुख्य सीवीज़ विधि present2 2 लागू करता है – आप मुश्किल से डीबग त्रुटियों या क्रैश के साथ समाप्त कर सकते हैं प्रतिनिधि इस से बचने में आपकी मदद करते हैं।
  • एक बार वीसी 1 को खारिज कर दिया जाता है, यह पूर्णत: ब्लॉक को निष्पादित करने के लिए नहीं है … या है ना? क्या स्वयं का प्रतिनिधित्व करता है ViewController किसी भी अधिक मतलब है? आप नहीं जानते (न तो मैं …) एक प्रतिनिधि के साथ, आपको इस अनिश्चितता नहीं है
  • जब मैं इस विधि को चलाने की कोशिश करता हूं, तो यह केवल चेतावनी या त्रुटियों के साथ लटका हुआ है

तो कृपया … प्रतिनिधिमंडल जानने के लिए समय ले लो!

Update2

आपकी टिप्पणी में आपने इसे वीसी 2 के बटन हैंडलर में खारिज कर इसे काम करने में कामयाब रहे हैं:

  [self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil]; 

यह निश्चित रूप से बहुत सरल है, लेकिन इससे आपको कई मुद्दों के साथ छोड़ दिया जाता है

कसा हुआ संयोजन
आप अपने दृश्य कंट्रोलर संरचना को एक साथ कठिन बनाते हैं। उदाहरण के लिए, यदि आप mainVC से पहले एक नया दृश्य नियंत्रक डालने के लिए होते हैं, तो आपका आवश्यक व्यवहार टूट जाएगा (आप पहले से नेविगेट करेंगे)। वीसी 1 में आपको वीसी 2 # इंपोर्ट करना पड़ा है। इसलिए आपके पास बहुत अधिक अंतर निर्भरताएं हैं, जो ओओपी / एमवीसी उद्देश्यों को तोड़ता है।

प्रतिनिधियों का उपयोग करना, न तो वीसी 1 और वीसी 2 को मुख्य सीवीसी या इसके पूर्ववर्ती के बारे में कुछ जानने की जरूरत है ताकि हम सब कुछ ढीले-युग्मित और मॉड्यूलर रख सकें।

याद
वीसी 1 दूर नहीं गया है, आप अभी भी दो पॉइंटर्स इसे रख सकते हैं:

  • मुख्यवीसी के presentedViewController ViewController संपत्ति
  • वीसी 2 के presentingViewController ViewController संपत्ति

आप इसे लॉगिंग द्वारा परीक्षण कर सकते हैं, और यह भी VC2 से ऐसा करके

 [self dismissViewControllerAnimated:YES completion:nil]; 

यह अभी भी काम करता है, फिर भी आपको वीसी 1 पर वापस चला जाता है।

मुझे एक स्मृति रिसाव की तरह लगता है

इस चेतावनी में आप यहां मिल रहे चेतावनी में हैं:

 [self presentViewController:vc2 animated:YES completion:nil]; [self dismissViewControllerAnimated:YES completion:nil]; // Attempt to dismiss from view controller <VC1: 0x715e460> // while a presentation or dismiss is in progress! 

तर्क टूट जाता है, जैसा कि आप वर्तमान उपकुलपति को खारिज करने का प्रयास कर रहे हैं , जिसमें वीसी 2 प्रस्तुत उपाध्यक्ष है। दूसरे संदेश वास्तव में निष्पादित नहीं होता है – ठीक है शायद कुछ सामान होता है, लेकिन आप दो बिंदुओं के साथ अभी भी एक ऑब्जेक्ट के साथ छोड़ते हैं जिसे आपने सोचा था कि आपने छुटकारा पा लिया है। ( संपादित करें – मैंने इसे चेक किया है और यह इतना बुरा नहीं है, जब आप mainVC पर वापस आ जाते हैं तो दोनों ऑब्जेक्ट दूर जाते हैं )

यह कहने का एक बहुत लंबा रास्ता है – कृपया, प्रतिनिधियों का उपयोग करें। अगर यह मदद करता है, तो मैंने यहां पैटर्न का एक संक्षिप्त विवरण दिया था:
क्या नियंत्रक हमेशा एक खराब अभ्यास में गुजर रहा है?

3 अपडेट करें
यदि आप वास्तव में प्रतिनिधियों से बचना चाहते हैं, तो यह सबसे अच्छा तरीका हो सकता है:

वीसी 1 में:

 [self presentViewController:VC2 animated:YES completion:nil]; 

लेकिन कुछ भी खारिज मत करो … जैसा कि हम जानते हैं, यह वास्तव में वैसे भी नहीं होता है।

वीसी 2 में:

 [self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 

जैसा कि हमने (पता है) हमने वीसी 1 को खारिज नहीं किया है, हम वीसी 1 के माध्यम से मेनवीसी तक पहुंच सकते हैं। मेनवीसी वीसी 1 को खारिज कर देता है क्योंकि VC1 चला गया है, यह पेश किया गया है VC2 इसके साथ चला जाता है, इसलिए आप एक साफ राज्य में MainVC पर वापस आ गए हैं।

यह अभी भी अत्यधिक युग्मित है, क्योंकि वीसी 1 को वीसी 2 के बारे में जानने की जरूरत है, और वीसी 2 को यह जानना आवश्यक है कि यह मेनवीसी-> वीसी 1 के माध्यम से पहुंचा था, लेकिन यह सबसे अच्छा है कि आप कुछ विशिष्ट प्रतिनिधिमंडल के बिना नहीं जा सकते हैं।

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

 UIViewController presentingVC = [self presentingViewController]; [self dismissViewControllerAnimated:YES completion: ^{ [presentingVC presentViewController:vc2 animated:YES completion:nil]; }]; 

ध्यान दें कि self.presentingViewController को किसी अन्य चर में संग्रहीत किया जाता है, क्योंकि vc1 स्वयं को खारिज करने के बाद, आपको इसके बारे में कोई संदर्भ नहीं करना चाहिए।

स्विफ्ट में उदाहरण, ऊपर फाउंड्री के स्पष्टीकरण को दर्शाते हुए और एप्पल के दस्तावेज:

  1. एप्पल के प्रलेखन और ऊपर फाउंड्री के स्पष्टीकरण (कुछ त्रुटियों को ठीक करने) पर आधारित, वर्तमान दृश्यकंट्रोलर संस्करण प्रतिनिधि डिजाइन पैटर्न का उपयोग करते हुए:

ViewController.swift

 import UIKit protocol ViewControllerProtocol { func dismissViewController1AndPresentViewController2() } class ViewController: UIViewController, ViewControllerProtocol { @IBAction func goToViewController1BtnPressed(sender: UIButton) { let vc1: ViewController1 = self.storyboard?.instantiateViewControllerWithIdentifier("VC1") as ViewController1 vc1.delegate = self vc1.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal self.presentViewController(vc1, animated: true, completion: nil) } func dismissViewController1AndPresentViewController2() { self.dismissViewControllerAnimated(false, completion: { () -> Void in let vc2: ViewController2 = self.storyboard?.instantiateViewControllerWithIdentifier("VC2") as ViewController2 self.presentViewController(vc2, animated: true, completion: nil) }) } } 

ViewController1.swift

 import UIKit class ViewController1: UIViewController { var delegate: protocol<ViewControllerProtocol>! @IBAction func goToViewController2(sender: UIButton) { self.delegate.dismissViewController1AndPresentViewController2() } } 

ViewController2.swift

 import UIKit class ViewController2: UIViewController { } 
  1. ऊपर फाउंड्री के स्पष्टीकरण (कुछ त्रुटियों को ठीक करने) पर आधारित, पुश ViewController संस्करण प्रतिनिधि डिजाइन पैटर्न का उपयोग कर:

ViewController.swift

 import UIKit protocol ViewControllerProtocol { func popViewController1AndPushViewController2() } class ViewController: UIViewController, ViewControllerProtocol { @IBAction func goToViewController1BtnPressed(sender: UIButton) { let vc1: ViewController1 = self.storyboard?.instantiateViewControllerWithIdentifier("VC1") as ViewController1 vc1.delegate = self self.navigationController?.pushViewController(vc1, animated: true) } func popViewController1AndPushViewController2() { self.navigationController?.popViewControllerAnimated(false) let vc2: ViewController2 = self.storyboard?.instantiateViewControllerWithIdentifier("VC2") as ViewController2 self.navigationController?.pushViewController(vc2, animated: true) } } 

ViewController1.swift

 import UIKit class ViewController1: UIViewController { var delegate: protocol<ViewControllerProtocol>! @IBAction func goToViewController2(sender: UIButton) { self.delegate.popViewController1AndPushViewController2() } } 

ViewController2.swift

 import UIKit class ViewController2: UIViewController { } 

राडू सिमियोनेस्कू – बढ़िया काम! और स्विफ्ट प्रेमी के लिए आपके समाधान के नीचे:

 @IBAction func showSecondControlerAndCloseCurrentOne(sender: UIButton) { let secondViewController = storyboard?.instantiateViewControllerWithIdentifier("ConrollerStoryboardID") as UIViewControllerClass // change it as You need it var presentingVC = self.presentingViewController self.dismissViewControllerAnimated(false, completion: { () -> Void in presentingVC!.presentViewController(secondViewController, animated: true, completion: nil) }) } 

मैं यह चाहता था:

MapVC पूर्ण स्क्रीन में एक मानचित्र है।

जब मैं एक बटन दबाता हूं, तो मानचित्र के ऊपर पॉपअपVC (पूर्ण स्क्रीन में नहीं) खोलता है

जब मैं पॉपअपवीसी में एक बटन दबाता हूं, यह MapVC पर वापस आ जाता है, और फिर मैं viewDidAppear निष्पादित करना चाहता हूं।

इसे मैने किया है:

MapVC.m: बटन कार्रवाई में, एक प्रोग्राम प्रोग्राम के अनुसार, और प्रतिनिधि सेट करें

 - (void) buttonMapAction{ PopupVC *popvc = [self.storyboard instantiateViewControllerWithIdentifier:@"popup"]; popvc.delegate = self; [self presentViewController:popvc animated:YES completion:nil]; } - (void)dismissAndPresentMap { [self dismissViewControllerAnimated:NO completion:^{ NSLog(@"dismissAndPresentMap"); //When returns of the other view I call viewDidAppear but you can call to other functions [self viewDidAppear:YES]; }]; } 

PopupVC.h: @ इंटरफेस से पहले, प्रोटोकॉल जोड़ें

 @protocol PopupVCProtocol <NSObject> - (void)dismissAndPresentMap; @end 

@ इंटरफेस के बाद, एक नई संपत्ति

 @property (nonatomic,weak) id <PopupVCProtocol> delegate; 

PopupVC.m:

 - (void) buttonPopupAction{ //jump to dismissAndPresentMap on Map view [self.delegate dismissAndPresentMap]; } 

मैंने प्रस्तुत करते समय UINavigationController का उपयोग करके इस समस्या का समाधान किया है। मेनवीसी में, वीसी 1 को पेश करते समय

 let vc1 = VC1() let navigationVC = UINavigationController(rootViewController: vc1) self.present(navigationVC, animated: true, completion: nil) 

वीसी 1 में, जब मैं वीसी 2 को दिखाऊंगा और उसी समय वीसी 1 को खारिज कर दूँगा (केवल एक एनीमेशन), मैं एक पुश एनीमेशन कर सकता हूं

 let vc2 = VC2() self.navigationController?.setViewControllers([vc2], animated: true) 

और वीसी 2 में, दृश्य नियंत्रक को बंद करते समय, हम सामान्य रूप से उपयोग कर सकते हैं:

 self.dismiss(animated: true, completion: nil)