2010-07-12 13 views
20

तो तीन दृश्य नियंत्रकों के साथ एक ढेर है जहां ए रूट है, बी पहला मोडल व्यू कंट्रोलर है और सी तीसरा मोडल वीसी है। मैं एक बार में सी से ए में जाना चाहता हूं। मैंने this solution to dismiss की कोशिश की है। यह काम है लेकिन सही तरीके से नहीं। वह तब होता है जब अंतिम दृश्य नियंत्रक को खारिज कर दिया जाता है, यह पहले दिखाए जाने से पहले दूसरे दृश्य नियंत्रक को दिखाएगा। जो मैं खोज रहा हूं वह तीसरे वीसी से दूसरे दृश्य को देखे बिना एक अच्छी एनीमेशन में पहली बार पहुंचने का एक तरीका है। इस पर कोई मदद बहुत सराहना की है।एक बार में कई मोडल व्यू कंट्रोलर को खारिज कर रहा है?

+0

(आपको स्पष्ट रूप से प्रतिनिधि तरीकों या अन्य रूप में समान रूप रोमांचक डिजाइन पैटर्न के साथ इस पूरे हिस्से की जगह ले सकता, महत्वपूर्ण हिस्सा viewControllerB स्तर पर बर्खास्तगी को संभालने के लिए है) एक मोडल व्यू कंट्रोलर को और अधिक खारिज करने का अधिक सामान्य तरीका है [यहां] (https://stackoverflow.com/a/44583711/1151916) – Ramis

उत्तर

20

सुनिश्चित करें कि आप केवल dismissModalViewControllerAnimated: पर कॉल कर रहे हैं।

मुझे पता चला है कि प्रत्येक स्टैक्ड मोडल व्यू कंट्रोलर को खारिज करने के लिए पूछने से दोनों को एनिमेट कर दिया जाएगा।

आपके पास: A =modal> B =modal> C

आप केवल बुलाना चाहिए [myViewControllerA dismissModalViewControllerAnimated:YES]

आप [myViewControllerB dismissModalViewControllerAnimated:YES] उपयोग करते हैं, यह सामान्य में सी खारिज करेगा, और न बी (unstacked) की वजह से, का उपयोग यह बी खारिज होता है (प्रतिक्रियाकर्ता श्रृंखला ए को संदेश को बुलबुला कर रहा है)। आपके द्वारा वर्णित स्टैक्ड परिदृश्य में बी एक मूल दृश्य नियंत्रक है और इसे एक मोडल व्यू कंट्रोलर होने पर प्राथमिकता दी जाती है।

+7

ठीक है अब तक मैं इसका उपयोग करता हूं: [[[self parentViewController] parentViewController] dismissModalViewControllerAnimated: YES]; वह रूट व्यू कंट्रोलर का उपयोग करेगा। हालांकि, यह अभी भी एक दूसरे के लिए दूसरे वीसी दिखाता है। – sebrock

+0

ओह, और मुझे कहना चाहिए कि मैं उपयोगिता टेम्पलेट का उपयोग करता हूं और दूसरा वीसी फ्लिपसाइड दृश्य है। तीसरा फ्लिपसाइड से तत्काल एक मोडल वीसी है। – sebrock

+1

नोट: आईओएस 5 में यह "प्रस्तुत करने के लिए व्यू कंट्रोलर" में बदल गया है http://game4mob.com/index.php/jawbreaker/66-dismiss-modal-view-in-ios5-sdk –

-5

आप जो उपयोग करना चाहते हैं वह popToRootViewControllerAnimated: है। यह आपको सभी हस्तक्षेप किए बिना रूट नियंत्रक के पास ले जाता है।

+1

यह एक अच्छा समाधान है यदि ए 'UINavigationController' – ohhorob

+1

ओह हाँ की जड़ है। मैं बस जाग गया, इसलिए मैंने उसे पकड़ नहीं लिया। – lucius

0

आप इन रूटल व्यू कंट्रोलर को अपने रूट व्यू कंट्रोलर पर खारिज कर सकते हैं। हालांकि

UIViewController *viewController = yourRootViewController; 

    NSMutableArray *array = [NSMutableArray array]; 
    while (viewController.modalViewController) { 
     [array addObject:viewController]; 
     viewController = viewController.modalViewController; 
    } 

    for (int i = 0; i < array.count; i++) { 
     UIViewController *viewController = array[array.count-1-i]; 
     [viewController dismissModalViewControllerAnimated:NO]; 
    } 
3

स्वीकार किए जाते हैं जवाब मेरे लिए काम किया है, यह अब पुरानी हो सकती है और एक अजीब लग रही एनीमेशन जहां सर्वोच्च मोडल तुरंत गायब हो जाते हैं और एनीमेशन पीछे modalview पर होगा छोड़ दिया है। मैंने इससे बचने के लिए कई चीजों की कोशिश की और इसे अच्छा लगने के लिए एक हैक का उपयोग करने के लिए समाप्त हो गया। नोट: (केवल iOS8 + में परीक्षण किया गया है, लेकिन काम करना चाहिए iOS7 +)

असल में, viewControllerA viewControllerB rootview के रूप में के साथ एक UINavigationController बनाता है और यह रीति से प्रस्तुत करता है।

// ViewControllerA.m 
- (void)presentViewB { 
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] init]; 
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewControllerB]; 

    navigationController.modalPresentationStyle = UIModalPresentationFormSheet; 
    [self presentViewController:navigationController animated:YES completion:nil]; 
} 

अब viewControllerB में हम viewControllerC उसी तरह पेश करने के लिए जा रहे हैं, लेकिन हम इसे पेश करने के बाद, हम viewControllerB के नेविगेशन नियंत्रक पर दृश्य परत के ऊपर viewControllerC का एक स्नैपशॉट डाल करने के लिए जा रहे हैं। फिर, जब viewControllerC बर्खास्तगी के दौरान गायब हो जाता है, तो हम परिवर्तन नहीं देखेंगे और एनीमेशन सुंदर दिखाई देगा।

//ViewControllerB.m 
- (void)presentViewC { 
    ViewControllerC *viewControllerC = [[ViewControllerC alloc] init]; 

    // Custom presenter method to handle setting up dismiss and snapshotting 
    // I use this in a menu that can present many VC's so I centralized this part. 
    [self presentViewControllerForModalDismissal:viewControllerC]; 
} 

नीचे मेरी सहायक कार्यों उस दृश्य प्रस्तुत करते हैं और बर्खास्तगी को संभालने के लिए किया जाता है। ध्यान देने योग्य एक बात, मैं ऑटो लेआउट बाधाओं को जोड़ने के लिए Purelayout का उपयोग कर रहा हूं। आप उन्हें https://github.com/PureLayout/PureLayout

#pragma mark - Modal Presentation Helper functions 
- (void)presentViewControllerForModalDismissal:(UIViewController*)viewControllerToPresent { 
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewControllerToPresent]; 
    navigationController.modalPresentationStyle = UIModalPresentationFormSheet; 

    // Ensure that anything we are trying to present with this method has a dismissBlock since I don't want to force everything to inherit from some base class. 
    NSAssert([viewControllerToPresent respondsToSelector:NSSelectorFromString(@"dismissBlock")], @"ViewControllers presented through this function must have a dismissBlock property of type (void)(^)()"); 
    [viewControllerToPresent setValue:[self getDismissalBlock] forKey:@"dismissBlock"]; 

    [self presentViewController:navigationController animated:YES completion:^{ 
     // We want the presented view and this modal menu to dismiss simultaneous. The animation looks weird and immediately becomes the menu again when dismissing. 
     // So we are snapshotting the presented view and adding it as a subview so you won't see the menu again when dismissing. 
     UIView *snapshot = [navigationController.view snapshotViewAfterScreenUpdates:NO]; 
     [self.navigationController.view addSubview:snapshot]; 
     [snapshot autoPinEdgesToSuperviewEdges]; 
    }]; 
} 

- (void(^)()) getDismissalBlock { 
    __weak __typeof(self) weakSelf = self; 
    void(^dismissBlock)() = ^{ 
     __typeof(self) blockSafeSelf = weakSelf; 
     [blockSafeSelf.navigationController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 
    }; 

    return dismissBlock; 
} 

पर मैन्युअल रूप से जोड़ या Purelayout प्राप्त करने के लिए इस संशोधित कर सकते हैं अब हम सिर्फ यह सुनिश्चित करने के हम dismissBlock ViewControllerC में एक संपत्ति के रूप में परिभाषित किया गया है की जरूरत है।ज

// ViewControllerC.h 
@interface ViewControllerC : UIViewController 
@property (nonatomic, copy) void (^dismissBlock)(void); 
@end 

//ViewControllerC.m 
// Make an method to handle dismissal that is called by button press or whatever logic makes sense. 
- (void)closeButtonPressed { 
    if (_dismissBlock) {// If the dismissblock property was set, let the block handle dismissing 
     _dismissBlock(); 
     return; 
    } 

    // Leaving this here simply allows the viewController to be presented modally as the base as well or allow the presenter to handle it with a block. 
    [self dismissViewControllerAnimated:YES completion:nil]; 
} 

आशा इस मदद करता है, खुश प्रोग्रामिंग :)

+0

एक कामकाजी समाधान के लिए अपवोट, लेकिन यह सिर्फ पागल है (इसके लाभ की तुलना में) –

+1

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

+0

बिल्कुल सच है। मैं एक और रास्ता चला गया और एक दूसरे के बाद दृश्य नियंत्रकों को खारिज कर दिया (यह समस्या का समाधान नहीं है, लेकिन यह काम करता है और _that_ बदसूरत नहीं है) –