नेविगेशन कंट्रोलर से एक बार में दो दृश्य कैसे दिखाऊं?


90

मैं पहले दृश्य पर वापस नेविगेशन स्टैक पर तीसरे दृश्य को पॉप करना चाहता हूं।

मुझे पता है कि एक बार में एक दृश्य को कैसे पॉप किया जाए:

[self.navigationController popViewControllerAnimated:YES];

लेकिन मैं एक बार में दो कैसे करूँ?


2
मेटा टिप्पणी: @lubilis सभी तरह से उत्तर देता है कि सबसे अच्छा है। शीर्ष रेटेड उत्तर अपने समय में अच्छे थे लेकिन अब प्रासंगिक नहीं हैं।
n13

जवाबों:


132

आप नेविगेशन नियंत्रक स्टैक के बीच भी कूदने के लिए इसे आज़मा सकते हैं

NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
for (UIViewController *aViewController in allViewControllers) {
    if ([aViewController isKindOfClass:[RequiredViewController class]]) {
        [self.navigationController popToViewController:aViewController animated:NO];
    }
}

6
imo यह अब तक का सबसे अच्छा तरीका है, लेकिन आपको अपने uinavigation कंट्रोलर को self.navigationcontroller
henghonglee

2
मैं सहमत हूं, यह सबसे अच्छा समाधान है अगर उपयोगकर्ता स्टैक को एक निश्चित दृश्य-नियंत्रक पर वापस करना चाहेगा। मान लीजिए कि आपको पता नहीं है कि कौन सा व्यू कंट्रौलर है, आप अभी भी एक सिस्टम लागू कर सकते हैं, जिसमें आप यह निर्दिष्ट करेंगे कि आप स्टैक से पॉप अप करने के लिए कितने व्यू-कंट्रोलर चाहते हैं और ऑब्जेक्ट के साथ allViewControllers एरे से ऑब्जेक्ट व्यूऑन्ड्रोलर प्राप्त करें। 1 - राशि)। -1 क्योंकि सरणियाँ शून्य-आधारित संभोग हैं।
जोवन

1
इस घोल से प्यार करें। बिल्कुल वही जो मैं देख रहा था
डिज़ाइनर

3
यह भी काम करता है जब मूल नाविक से अधिक पुनरावृत्ति करता
अर्क सेगल

ध्यान दें! यह शुरू से अंत तक स्टैक को पुनरावृत्त करेगा -> बिल्कुल सही होने के लिए, आपको स्टैक को उल्टा करना चाहिए। क्योंकि अगर आपके पास एक ही तरह के कई VC हैं तो आप गलत VC को गलत क्रम में हटा देंगे।
स्टैकउंडरफ्लो

71

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

extension UINavigationController {

  func popToViewController(ofClass: AnyClass, animated: Bool = true) {
    if let vc = viewControllers.filter({$0.isKind(of: ofClass)}).last {
      popToViewController(vc, animated: animated)
    }
  }

  func popViewControllers(viewsToPop: Int, animated: Bool = true) {
    if viewControllers.count > viewsToPop {
      let vc = viewControllers[viewControllers.count - viewsToPop - 1]
      popToViewController(vc, animated: animated)
    }
  }

}

और इसे इस तरह उपयोग करें:

// pop to SomeViewController class
navigationController?.popToViewController(ofClass: SomeViewController.self)

// pop 2 view controllers
navigationController?.popViewControllers(viewsToPop: 2)

3
स्विफ्ट (विकल्प 1) के लिए, आप दोनों removeLastको बस के साथ बदल सकते हैं removeLast(2)
डोमिनिक के

नियंत्रकों के जीवनचक्र की कॉलिंग विधियों के बारे में क्या? DidAppear और ect
माइक

1
(स्विफ्ट 4) आप इस पंक्ति में कोष्ठक को गायब कर रहे हैं let vc = viewControllers[viewControllers.count - viewsToPop + 1], सही ढंग से काम करने के लिए आपको इसे बदलने की आवश्यकता है: let vc = viewControllers[viewControllers.count - (viewsToPop + 1)]याlet vc = viewControllers[viewControllers.count - viewsToPop - 1]
MMiroslav

@Miroslav अपने सही हैं। मैंने अपना उत्तर अपडेट कर दिया है। धन्यवाद /
हवलदार

1
नीचे अपना जवाब पोस्ट करने के बाद यह उत्तर अपडेट किया गया है। अनिवार्य रूप से मेरे कोड ^ _ ^
lubilis

44

आप "रूट" (पहले) दृश्य नियंत्रक के साथ पॉप कर सकते हैं popToRootViewControllerAnimated:

[self.navigationController popToRootViewControllerAnimated:YES];

// If you want to know what view controllers were popd:
// NSArray *popdViewControllers = [self.navigationController popToRootViewControllerAnimated:YES];

UINavigationControllerसंदर्भ :

रूट दृश्य नियंत्रक को छोड़कर स्टैक पर सभी व्यू कंट्रोलर्स को प्रदर्शित करता है और डिस्प्ले को अपडेट करता है।

मान वापस लौटें
व्यू व्यूअर की एक सरणी जो स्टैक से पॉप अप की जाती है।


1
हा, विश्वास नहीं कर सकता कि मैंने इतने लंबे समय तक इस तरह के एक सरल उत्तर की तलाश में, धन्यवाद!
एडम वेट

1
स्विफ्ट 3: self.navigationController; .popToRootViewController (एनिमेटेड: सच);
डायनाकारेंम्स

ठीक है कि मैं क्या देख रहा था!
Canucklesandwich

29
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];   

objectAtIndex: 1 -> आप जिस भी इंडेक्स को पॉप करना चाहते हैं उसे पास कर सकते हैं


चाल के लिए धन्यवाद, मैं इसे गलत तरीके से करने के बारे में था।
लाइनस डेस

18

स्विफ्ट 2 - xCode 7.3

यह UIViewControllers को पॉप करने के लिए एक बहुत ही उपयोगी एक्सटेंशन हो सकता है:

extension UINavigationController {

    func popToViewControllerOfType(classForCoder: AnyClass) {
        for controller in viewControllers {
            if controller.classForCoder == classForCoder {
                popToViewController(controller, animated: true)
                break
            }
        }
    }

    func popViewControllers(controllersToPop: Int, animated: Bool) {
        if viewControllers.count > controllersToPop {
            popToViewController(viewControllers[viewControllers.count - (controllersToPop + 1)], animated: animated)
        } else {
            print("Trying to pop \(controllersToPop) view controllers but navigation controller contains only \(viewControllers.count) controllers in stack")
        }
    }
}

2
इसके लिए और अधिक उत्थान की जरूरत है। मैं उस विस्तार को लिखने वाला था। मैं सिर्फ तुम्हारा धन्यवाद इस्तेमाल करूंगा;)
n13

1
@ n13 यह कैसे आया है यह मित्र के उत्तर से बेहतर है?
रात्रि

1
एक एक्सटेंशन का उपयोग बहुत क्लीनर कोड के लिए करता है। आप budidino का उत्तर ले सकते हैं और उसमें से विस्तार कर सकते हैं लेकिन यह आपको प्रयास को बचाता है। साथ ही यह उत्तर त्रुटि मामलों की जांच करता है, और त्रुटियों को इनायत से संभालता है (जैसे आपके पास अधिक से अधिक पॉप करने की कोशिश कर रहा है)
n13

1
मुझे यह उत्तर पसंद है। मुझे पुनर्विचार किया और मेरे द्वारा पोस्ट किए गए उत्तर को अपडेट करें। मैंने अपने कोड को व्यू कॉन्ट्रॉलर्स एरे में खोजे गए वर्ग के अंतिम उदाहरण के लिए पॉप बना दिया क्योंकि यह संभवतः वांछित व्यवहार है।
मित्रो

15

यदि आप केवल एक बार में 2 पॉप करना चाहते हैं क्योंकि आपका rootViewController (तरीका) 'गहरा' है, तो 2 आप उदाहरण के लिए UIviewController में एक श्रेणी जोड़ने पर विचार कर सकते हैं:

UINavigationController + popTwice.h

#import <UIKit/UIKit.h>
@interface UINavigationController (popTwice)

- (void) popTwoViewControllersAnimated:(BOOL)animated;

@end

UINavigationController + popTwice.m

#import "UINavigationController+popTwice.h"

@implementation UINavigationController (popTwice)

- (void) popTwoViewControllersAnimated:(BOOL)animated{
    [self popViewControllerAnimated:NO];
    [self popViewControllerAnimated:animated];
}

@end

#import "UINavigationController+popTwice.h"अपने कार्यान्वयन में श्रेणी को कहीं आयात करें और कोड की इस पंक्ति का उपयोग एक ही बार में 2 नियंत्रकों को पॉप करने के लिए करें:

[self.navigationController popTwoViewControllersAnimated:YES];

क्या यह महान नहीं है? :)


6
यदि आपको तीन दृश्य पॉप करने की आवश्यकता है, तो आप "UINavigationController + popThrice.m" लिखेंगे ??????
मिलो

8
आप पॉप करने के लिए viewControllers की संख्या के लिए एक पैरामीटर में पास कर सकते हैं, और [self popViewControllerAnimated: NO] लपेटें; गिनती -1 के लिए एक लूप के भीतर।
noRema

यह सही तरीका नहीं है, यदि आप 2,3 को बर्तन देना चाहते हैं, ... कोई भी नियंत्रक लूप द्वारा इसकी पहचान करता है और फिर [self.navigationController popToViewControllerAnimated: YES]; का उपयोग करता है। यह उपर्युक्त बहुत खराब कोडिंग है और फ़्लिकर UI और बुरे उपयोगकर्ता अनुभव दिखा सकता है।
विक्की धस

10

स्विफ्ट 4:

func popViewControllerss(popViews: Int, animated: Bool = true) {
    if self.navigationController!.viewControllers.count > popViews
    {
        let vc = self.navigationController!.viewControllers[self.navigationController!.viewControllers.count - popViews - 1]
         self.navigationController?.popToViewController(vc, animated: animated)
    }
}

फिर इस विधि का उपयोग करें

self.popViewControllerss(popViews: 2)

अच्छा एक, मैं क्या देख रहा था। धन्यवाद।
maddysan

6

आप भी इसे आजमा सकते हैं: -

[self.navigationController popToViewController:yourViewController animated:YES];

6
//viewIndex = 1;
//viewIndex = 2;
//viewIndex = 3;

// **[viewControllers objectAtIndex: *put here your viewindex number*]

NSArray *viewControllers = [self.navigationController viewControllers];
[self.navigationController popToViewController:[viewControllers objectAtIndex:viewIndex] animated:NO];


4

स्विफ्ट 3 में , आप नेविगेशन कंट्रोलर से एक, दो या दो से अधिक व्यू कॉन्ट्रोलर्स को पॉप कर सकते हैं

let viewControllers = self.navigationController!.viewControllers as [UIViewController]
    for aViewController:UIViewController in viewControllers {
        if aViewController.isKind(of: FromWhereYouWantToGoController.self) {
            _ = self.navigationController?.popToViewController(aViewController, animated: true)
        }
    }

यहाँ FromWhereYouWantToGoController गंतव्य नियंत्रक है। आशा करता हूँ की ये काम करेगा।


3

आप प्रारंभिक दृश्य नियंत्रक (आप जिस पर वापस आना चाहते हैं) पास कर सकते हैं और फिर अंतिम दृश्य में इस लाइन को कॉल कर सकते हैं:

[self.navigationController popToViewController:yourInitialViewController animated:YES];

एल


3

मुझे यह उत्तर यहां नहीं दिखाई दिया। यदि आप केवल कुछ पॉप करना चाहते हैं (रूट के सभी तरीके नहीं), तो आप बस self.navigationController.viewControllers के माध्यम से वर्ग प्रकारों के लिए जाँच कर सकते हैं, या यदि आपके पास एक संदर्भ उपयोग है:

for (UIViewController *aViewController in self.navigationController.viewControllers) {
   if ([aViewController isKindOfClass:[SMThumbnailViewController class]]) {
      [self.navigationController popToViewController:aViewController animated:YES];
   }
}

2

आप मूल दृश्य नियंत्रक पर वापस पॉप कर सकते हैं

[self.navigationController popToRootViewControllerAnimated:YES];

या, यदि आप जिस दृश्य को पॉप करना चाहते हैं वह पहले वाला नहीं है, तो आपको अपने पिछले दृश्य के दृश्य में फिर से पॉप करना होगा।


2

यहाँ एक छोटा सा कार्य है जो मैं X ViewControllers पर वापस जाने के लिए उपयोग कर रहा हूँ:

-(void)backMultiple:(id)data {
    int back = 2; //Default to go back 2 
    int count = [self.navigationController.viewControllers count];

    if(data[@"count"]) back = [data[@"count"] intValue];

    //If we want to go back more than those that actually exist, just go to the root
    if(back+1 > count) {
        [self.navigationController popToRootViewControllerAnimated:YES];
    }
    //Otherwise go back X ViewControllers 
    else {
        [self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:count-(back+1)] animated:YES];
    }
}

2

दो बार या अधिक पॉपिंग के स्विफ्ट संस्करण (स्विफ्ट 1.2 / Xcode 6.3.1) के रूप में

 var viewControllers = self.navigationController?.viewControllers
 viewControllers?.removeLast()
 viewControllers?.removeLast()
 self.navigationController?.setViewControllers(viewControllers, animated: true)

या

 var viewControllers = self.navigationController?.viewControllers
 var viewsToPop = 2
 var end = (viewControllers?.count)!
 var start = end - viewsToPop
 viewControllers?.removeRange(Range<Int>(start: start, end: end))
 self.navigationController?.setViewControllers(viewControllers, animated: true)

1

आप UIViewControllers के स्टैक का उपयोग कर सकते हैं। 1. स्टैक में सभी viewControllers की सरणी प्राप्त करें। 2. मैं पूरे व्यू के माध्यम से पढ़ता हूं और
क्लास के प्रकार का मिलान करके वांछित व्यू कंट्रोलर ढूंढता हूं । 3. ViewController पॉप।

func popToSpecificViewC
{
let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController];
        for viewController:UIViewController in viewControllers
        {
            if viewController.isKind(of: WelcomeViewC.self)
            {
                _ = self.navigationController?.popToViewController(viewController, animated: true)
            }
        }
}

0

एक साधारण UINavigationController एक्सटेंशन का उपयोग करना :

extension UINavigationController {
    func popViewControllers(_ count: Int) {
        guard viewControllers.count > count else { return }
        popToViewController(viewControllers[viewControllers.count - count - 1], animated: true)
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.