Bir gezinti denetleyicisinden aynı anda iki görünümü nasıl açarım?


92

Gezinme yığınındaki üçüncü görünüme tekrar ilk görünüme geçmek istiyorum.

Tek seferde bir görünümü nasıl açacağımı biliyorum:

[self.navigationController popViewControllerAnimated:YES];

Ama aynı anda nasıl iki tane yaparım?


2
Meta yorumu: @lubilis en iyisi oradaki yanıtın sonuna kadar. En çok oy alan cevaplar kendi zamanında iyiydi ancak artık geçerli değil.
n13

Yanıtlar:


133

Bunu gezinme denetleyicisi yığını arasında da Atlamak için deneyebilirsiniz.

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 bu kadar iyi yöntemdir, ancak self.navigationcontroller kullanarak uinavigation denetleyicisi başvuruda bulunmalıdır
henghonglee

2
Kabul ediyorum, kullanıcı yığını belirli bir görüntü denetleyicisine geri döndürmek isterse bu en iyi çözümdür. Diyelim ki hangi viewcontroller olduğunu bilmiyorsunuz, yine de yığıntan kaç tane viewcontrollers'ı açıp hedef viewcontroller'ı objectAtIndex ile allViewControllers dizisinden almak istediğinizi belirleyeceğiniz bir sistem uygulayabilirsiniz: (allViewControllers.count - 1 - miktar). -1 çünkü diziler sıfır tabanlıdır.
Jovan

1
Bu çözümü seviyorum. Tam olarak aradığım şey
Designer023

3
Orijinal gezgin-> viewControllers dizisi üzerinde yineleme yaparken de çalışır (bunu değiştirilebilir bir diziye dönüştürmeye gerek yoktur)
Arik Segal

NOT! Bunun yığını başından sonuna kadar yineleyeceğini, tam olarak doğru olması için yığını ters çevirmelisiniz. Çünkü aynı türden birkaç VC'niz varsa, yığındaki yanlış VC'yi yanlış sırada kaldırırsınız.
StackUnderflow

72

İşte UINavigationControllersorununuzu çözebilecek iki uzantı. UIViewControllerBelirli bir sınıfa giren ilkini kullanmanızı tavsiye ederim :

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)
    }
  }

}

ve şu şekilde kullanın:

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

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

3
Swift için (seçenek 1), ikisini removeLastsadece ile değiştirebilirsiniz removeLast(2).
Dominic K

Denetleyicilerin yaşam döngüsü yöntemlerini çağırmaya ne dersiniz? DidAppear and ect
Mike Glukhov

1
(Swift 4) Bu satırda parantez eksik let vc = viewControllers[viewControllers.count - viewsToPop + 1], doğru çalışması için onu şu şekilde değiştirmeniz gerekiyor: let vc = viewControllers[viewControllers.count - (viewsToPop + 1)]veyalet vc = viewControllers[viewControllers.count - viewsToPop - 1]
MMiroslav

@MMiroslav haklısın. Cevabımı güncelledim. Thank you / Hvala;)
budidino

1
Bu cevap, cevabımı aşağıda gönderdikten sonra güncellenmiştir. Esasen
kodumun

44

Aşağıdakilerle "kök" (ilk) görünüm denetleyicisine geçebilirsiniz popToRootViewControllerAnimated:

[self.navigationController popToRootViewControllerAnimated:YES];

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

UINavigationControllerReferans :

Kök görünüm denetleyicisi dışında yığındaki tüm görünüm denetleyicilerini açar ve ekranı günceller.

Dönüş Değeri
Yığından çıkarılan bir görünüm denetleyicileri dizisi.


1
ha, bu kadar basit bir cevap için bu kadar uzun zaman harcadığıma inanamıyorum, teşekkürler!
Adam Waite

1
Swift 3: self.navigationController? .PopToRootViewController (animasyonlu: true);
dianakarenms

Tam olarak aradığım şey!
Canucklesandwich

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

objectAtIndex: 1 -> açmak istediğiniz dizini geçebilirsiniz


Numara için teşekkürler, tam da yanlış şekilde yapmak üzereydim.
Linus

18

Hızlı 2 - xCode 7.3

Bu, UIViewControllers'ı açmak için çok kullanışlı bir uzantı olabilir:

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
Bunun daha fazla oylamaya ihtiyacı var ... Tam da o uzantıyı yazmak üzereydim. Sadece seninkini kullanacağım;)
n13

1
@ n13 nasıl oluyor da bu budidino'nun cevabından daha iyi?
Crashalot

1
Bir uzantı kullanmak çok daha temiz kod sağlar. Budidino'nun cevabını alıp bir uzantı yapabilirsiniz ama bu sizi çabadan kurtarır. Ayrıca bu cevap, hata durumlarını kontrol eder ve hataları zarif bir şekilde ele alır (örneğin, sahip olduğunuzdan daha fazla pop yapmaya çalışmak)
n13

1
Bu cevabı beğendim. Gönderdiğim yanıtı yeniden düşünmemi ve güncellememi sağladı. Kodumu viewControllers dizisindeki aranan sınıfın son örneğine açtım çünkü muhtemelen istenen davranış buydu.
budidino

15

Eğer rootViewController (yol) 'daha derin' olduğu için 2'yi aynı anda açmak istiyorsanız, 2, örneğin UIviewController'a bir kategori eklemeyi düşünebilirsiniz:

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

Kategoriyi #import "UINavigationController+popTwice.h"uygulamanızda bir yere aktarın ve bu kod satırını aynı anda 2 denetleyiciyi açmak için kullanın:

[self.navigationController popTwoViewControllersAnimated:YES];

harika değil mi? :)


6
Ya üç görünümü açmanız gerekirse, "UINavigationController + popThrice.m" yazacaksınız ??????
buluş

8
açılacak viewControllers sayısı için bir parametre geçirebilir ve [self popViewControllerAnimated: NO]; bir döngü içinde, count-1.
noRema

2,3'e pot yapmak istiyorsanız, bu doğru yol değildir, ... herhangi bir denetleyici onu döngü ile tanımlar ve sonra [self.navigationController popToViewControllerAnimated: YES]; 'i kullanır. Yukarıda belirtilen bu çok kötü bir kodlamadır ve titreyen kullanıcı arayüzü ve kötü kullanıcı deneyimi gösterebilir.
Vicky Dhas

10

Swift 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)
    }
}

Sonra Bu Yöntemi Kullanın

self.popViewControllerss(popViews: 2)

İyi bir, aradığım şey. Teşekkür ederim.
maddysan

6

Bunu da deneyebilirsiniz: -

[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
    NSMutableArray *newStack = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
    [newStack removeLastObject];
    [newStack removeLastObject];
    [self.navigationController setViewControllers:newStack animated:YES];

4

Swift 3'te , gezinme denetleyicisinden bir, iki veya daha fazla görüntü denetleyicisini şu şekilde açabilirsiniz

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

Burada FromWhereYouWantToGoController, hedef denetleyicidir. Umarım yardımcı olur.


3

İlk görünüm denetleyicisini (geri gelmek istediğiniz) geçebilir ve ardından son görünümde bu satırı çağırabilirsiniz:

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

L.


3

Bu cevabı burada görmedim. Yalnızca birkaçını açmak istiyorsanız (köke kadar değil), sınıf türlerini kontrol eden self.navigationController.viewControllers aracılığıyla yineleme yapabilirsiniz veya bir referansınız varsa bunu kullanın:

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

2

kök görünüm denetleyicisine geri dönebilirsiniz

[self.navigationController popToRootViewControllerAnimated:YES];

veya, açmak istediğiniz görünüm ilk değilse, önceki görünümünüzün görünümünde yeniden açmanız gerekir.


2

X ViewControllers'e geri dönmek için kullandığım küçük bir işlev:

-(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

(Swift 1.2 / Xcode 6.3.1) itibarıyla iki veya daha fazla patlama yapan Swift Sürümü

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

veya

 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 yığınını kullanabilirsiniz. 1. Yığındaki tüm viewControllers dizisini getir. 2. Tüm diziyi yineleyin
ve sınıf türünü eşleştirerek istenen viewController'ı bulun . 3. viewController'ı açın.

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

Basit bir UINavigationController uzantısı kullanarak :

extension UINavigationController {
    func popViewControllers(_ count: Int) {
        guard viewControllers.count > count else { return }
        popToViewController(viewControllers[viewControllers.count - count - 1], animated: true)
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.