2012-12-05 33 views
5

मेरे पास एक आईओएस ऐप है जिसमें लॉग इन व्यू है (LognnViewController) और एक बार जब उपयोगकर्ता सफलतापूर्वक प्रमाणीकृत हो जाता है तो उन्हें कुछ सरल विवरण दर्ज करने के लिए किसी अन्य दृश्य (DetailEntryViewController) पर ले जाया जाता है।
एक बार विवरण दर्ज किए जाने के बाद उपयोगकर्ता को ऐप के मुख्य भाग में ले जाया जाता है जिसमें एक टैब नियंत्रक (TabViewController) होता है जिसमें कई अन्य विचार होते हैं। LogInViewController DetailEntryViewController और DetailEntryViewController पर एक मोडल सेग्यू करता है, फिर टैबव्यू कंट्रोलर को एक मोडल सेग्यू करता है, इसलिए मेरे पास ऐप में जाने के लिए एक मोडल सेग्यू श्रृंखला है। एक उपयोगकर्ता लॉग आउट जब मैं सभी तरह LogInViewController के लिए वापस जाना चाहते हैं, लेकिन जब मैं एक कार्य करें:मॉडल सेग्यू चेन

[self.presentingViewController dismissModalViewControllerAnimated:YES]; 

... यह TabViewController पॉप और मैं पहली बार LogInViewController के बजाय DetailEntryViewController पर वापस अंत। क्या कोई तरीका है कि मैं आसानी से पहले व्यू कंट्रोलर पर वापस आ सकता हूं या इस मोडल सेग्यू चेन चीज को मुझसे रोकता हूं। मैं DetailEntryViewControllerviewWillAppear में कुछ कोड डाल करने के लिए उज्ज्वल विचार आया: कि स्वतः ही पॉप होता अगर उपयोगकर्ता लॉग आउट किया था, लेकिन स्पष्ट बनाने एक मॉडल नियंत्रक खारिज करने के लिए कॉल viewWillAppear में अनुमति नहीं है: viewDidLoad:, आदि

कोई यह कैसे करना है इस पर विचार?

उत्तर

0
[self.navigationController popToRootViewControllerAnimated:YES]; 
+0

कोई नेविगेशन नियंत्रक नहीं है ... यह एक टैब दृश्य एक दो चरणों मोडल segue श्रृंखला के द्वारा दिखाया नियंत्रक है। –

+0

आप नेविगेशन कंट्रोलर के बिना रूटव्यू पर वापस "पॉपिंग" कर रहे हैं? जिस व्यवहार के लिए आप पूछ रहे हैं वह एक UINavigationController बनाया गया सटीक कारण है। जब तक मैं कुछ याद नहीं कर रहा हूँ? –

+0

क्षमा करें मैं व्यू कंट्रोलर को हटाने की सामान्य समझ में "पॉप" का उपयोग कर रहा हूं। मेरे पास रूट नेविगेशन कंट्रोलर नहीं है - मेरे पास दो मानक व्यू कंट्रोलर हैं जो ऐप में मोडल सेग्यू के माध्यम से "सुरंग" हैं और फिर एक टैब व्यू कंट्रोलर जिसमें अन्य विचार शामिल हैं। मैंने जवाब निकाला, हालांकि ... नीचे देखें। –

8

मुझे लगता है कि यह आपके ऐप को लागू करने के लिए सबसे अच्छी संरचना नहीं है। मॉडल नियंत्रकों को प्रोग्राम के प्रवाह में अस्थायी बाधाओं के लिए माना जाता है, इसलिए आपकी मुख्य सामग्री प्राप्त करने के लिए एक मॉडल का उपयोग करना आदर्श नहीं है। जिस तरह से मैं यह करूँगा, अपने टैब बार नियंत्रक को विंडो के रूट व्यू कंट्रोलर को बनाना है, और फिर पहले टैब के नियंत्रक में, दृश्य नियंत्रक को सामान्य रूप से viewDidAppear विधि से प्रस्तुत करें, इसलिए यह तुरंत दिखाई देगा (आप संक्षेप में देखेंगे पहले टैब का दृश्य जब तक आप segue के गुण निरीक्षकों में "एनिमेट्स" बॉक्स को अनचेक नहीं करते)। उस से विवरण नियंत्रक प्रस्तुत करें, और फिर अपनी मुख्य सामग्री पर वापस जाने के लिए दोनों मोडल नियंत्रकों को खारिज करें। जब उपयोगकर्ता लॉग आउट करता है, तो उस लॉगिन नियंत्रक को फिर से प्रस्तुत करें। मैं इस विचार को इस तरह कार्यान्वित करता हूं। पहला टैब के दृश्य नियंत्रक में:

-(IBAction)goBackToMain:(id)sender { 
    [self.view.window.rootViewController dismissViewControllerAnimated:YES completion:nil]; 
} 
1

यह समझ से बाहर अपने आप को ... बस था:

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    _appStarting = YES; 
} 

-(void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    if (_appStarting) { 
     [self performSegueWithIdentifier:@"Login" sender:self]; 
     _appStarting = NO; 
    } 
} 

तो पिछले (दूसरा आपके मामले में) मॉडल दृश्य नियंत्रक में, मैं एक बटन विधि है "रूट" दृश्य नियंत्रक (LogInViewController) को पाने के लिए एक और स्तर ऊपर जाने के लिए और पाया कि इस चाल किया: जैसा कि मैंने कहा मैं तो बस presentingViewController (DetailEntryViewController) हो रही है

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

और n एक और स्तर ऊपर जा रहा है और उस नियंत्रक के प्रस्तुतकर्ता (LogInViewController) प्राप्त कर रहा है।

+1

जैसा कि मैंने अपने जवाब में कहा था, मुझे नहीं लगता कि यह एक अच्छी संरचना है। आप, और इस बोर्ड के कई अन्य लोग मोडल सेग्यू का दुरुपयोग कर रहे हैं - मोडल नियंत्रक प्रोग्राम के प्रवाह में अस्थायी बाधाओं के लिए हैं, न कि आपकी मुख्य सामग्री पर जाने का एक तरीका। यह काम करता है, लेकिन मुझे नहीं लगता कि यह एक अच्छा डिजाइन है। – rdelmar

+0

मैं पूरी तरह से यहां सहमत हूं और मुझे विश्वास है कि आपके द्वारा चुनी गई संरचना से भ्रम पैदा होगा कि नेविगेशन स्टैक का उपयोग कैसे किया जाना चाहिए। मुझे किसी अन्य मोडल व्यू में एक मोडल व्यू पेश करने और उसके बाद नेविगेट करने का कोई कारण नहीं दिखता है। क्या आप यहां अपने तर्क की व्याख्या कर सकते हैं? मॉडल दृश्यों को तब प्रदर्शित किया जाना है जिन्हें हटा दिया गया है। यदि आप उससे परे नेविगेट करना चाहते हैं तो मुझे विश्वास नहीं है कि यह सही विकल्प है और इस संरचना में बहुत गहरी गोता लगाने के बजाए तर्क को ठीक करना बेहतर होगा। लेकिन प्रत्येक के लिए खुद का है। ;-) –

1

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

तो मैं नियंत्रक की एक संपत्ति के रूप में मोडल नियंत्रकों के ढेर कार्यान्वित:

@interface ModalViewController : UIViewController 
@property (nonatomic, retain) NSMutableArray *modalControllers; 
@end 

जब पहली मोडल segue ढेर नियंत्रक के prepareForSegue विधि में बन जाता है जाता है कि मोडल नहीं निष्पादित होने

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"modalSegue"]) { 
     ModalViewController *controller = 
      (ModalViewController *)[segue destinationViewController]; 

     controller.modalControllers = [NSMutableArray arrayWithObject: controller]; 
    } 
} 

एक मॉडल नियंत्रक दूसरे करने के लिए ले जाता है जब गंतव्य

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([[segue identifier] isEqualToString:@"modalSegue"]) { 
     ModalViewController *destController = 
      (ModalViewController *)[segue destinationViewController]; 

     // add destination controller to stack 
     destController.modalControllers = _modalControllers; 
     [destController.modalControllers addObject: destController]; 
    } 
} 
(ModalViewCotroller की विधि में) ढेर में जोड़ा जाता है

एक बार में पूरे ढेर को खारिज करने के लिए सबसे मुश्किल हिस्सा था - आप अगले समाप्त होने से पहले पिछले नियंत्रक को बर्खास्त नहीं कर सकते हैं, इसलिए चक्र काम नहीं करता है, केवल रिकर्सिव ब्लॉक ने चाल की है, मेमोरी लीक से परहेज करते हुए trickiest (मैं अभी तक यह जांच करने के लिए है, लेकिन मैं this पर भरोसा):

- (IBAction)dismissAllModalControllers: (id)sender 
{ 
    // recursive block that dismisses one auth controller 
    // all these dances are to avoid leaks with ARC 
    typedef void (^voidBlockType)(); 
    __block void (^dismissController)(); 
    voidBlockType __weak dismissCopy = ^void(void) { 
     dismissController(); 
    }; 
    dismissController = ^void(void) { 
     int count = [_modalControllers count]; 
     if (count > 0) { 
      // get last controller 
      UIViewController *controller = 
       (UIViewController *)[_modalControllers lastObject]; 
      // remove last controller 
      [_modalControllers removeLastObject]; 
      // dismiss last controller 
      [controller 
       // the first controller in chain is dismissed with animation 
       dismissViewControllerAnimated: count == 1 ? YES : NO 
       // on completion call the block that calls this block recursively 
       completion: dismissCopy]; 
     } 
    }; 

    // this call dismisses all modal controllers 
    dismissController();   
}