Làm cách nào để bật hai chế độ xem cùng một lúc từ bộ điều khiển điều hướng?


90

Tôi muốn bật chế độ xem thứ ba trên ngăn xếp điều hướng trở lại chế độ xem đầu tiên.

Tôi biết cách bật một chế độ xem cùng một lúc:

[self.navigationController popViewControllerAnimated:YES];

Nhưng làm thế nào để làm hai cùng một lúc?


2
Nhận xét meta: @lubilis trả lời tất cả các cách dưới đó là tốt nhất. Các câu trả lời được xếp hạng cao nhất là tốt trong thời của họ nhưng không còn phù hợp nữa.
n13,

Câu trả lời:


132

Bạn có thể thử điều này để Nhảy giữa ngăn xếp bộ điều khiển điều hướng

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 đây là phương pháp tốt nhất cho đến nay, nhưng bạn nên tham khảo điều khiển uinavigation bạn sử dụng self.navigationcontroller
henghonglee

2
Tôi đồng ý, đây là giải pháp tốt nhất nếu người dùng muốn bật ngăn xếp trở lại một bộ điều khiển chế độ xem nhất định. Giả sử bạn không biết đó là bộ điều khiển chế độ xem nào, bạn vẫn có thể triển khai một hệ thống mà bạn sẽ chỉ định bao nhiêu bộ điều khiển chế độ xem bạn muốn bật ra khỏi ngăn xếp và lấy bộ điều khiển chế độ xem mục tiêu từ mảng allViewControllers với objectAtIndex: (allViewControllers.count - 1 - số tiền). -1 bởi vì mảng là tự nhiên dựa trên 0.
Jovan

1
Thích giải pháp này. Chính xác những gì tôi đang tìm kiếm
Designer023

3
Cũng hoạt động khi lặp qua điều hướng ban đầu-> mảng viewControllers (không cần chuyển đổi nó thành một mảng có thể thay đổi)
Arik Segal

GHI CHÚ! Điều này sẽ lặp lại ngăn xếp từ đầu -> đến cuối, để chính xác, bạn nên đảo ngược ngăn xếp. Bởi vì nếu bạn có nhiều VC cùng loại, bạn sẽ loại bỏ VC sai theo thứ tự sai trong ngăn xếp.
StackUnderflow

71

Đây là hai UINavigationControllerphần mở rộng có thể giải quyết vấn đề của bạn. Tôi khuyên bạn nên sử dụng cái đầu tiên bật lên một UIViewControllerlớp cụ thể:

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

}

và sử dụng nó như thế này:

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

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

3
Đối với Swift (tùy chọn 1), bạn có thể thay thế hai removeLastbằng chỉ removeLast(2).
Dominic K

Điều gì về việc gọi các phương thức trong vòng đời của bộ điều khiển? DidAppear và vv
Mike Glukhov

1
(Swift 4) Bạn thiếu dấu ngoặc trong dòng này let vc = viewControllers[viewControllers.count - viewsToPop + 1], để làm việc một cách chính xác bạn cần phải thay thế nó với: let vc = viewControllers[viewControllers.count - (viewsToPop + 1)]hoặclet vc = viewControllers[viewControllers.count - viewsToPop - 1]
MMiroslav

@MMiroslav của bạn là đúng. Tôi đã cập nhật câu trả lời của mình. Cảm ơn bạn / Hvala;)
budidino

1
Câu trả lời này đã được cập nhật sau khi tôi đăng câu trả lời của mình bên dưới. Về cơ bản là một bản sao mã của tôi ^ _ ^
lubilis

44

Bạn có thể bật bộ điều khiển chế độ xem "gốc" (đầu tiên) với popToRootViewControllerAnimated:

[self.navigationController popToRootViewControllerAnimated:YES];

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

UINavigationControllerTham khảo :

Dừng tất cả các bộ điều khiển chế độ xem trên ngăn xếp ngoại trừ bộ điều khiển chế độ xem gốc và cập nhật màn hình.

Giá trị trả lại
Một mảng bộ điều khiển chế độ xem được xuất hiện từ ngăn xếp.


1
ha, không thể tin được là tôi đã dành nhiều thời gian để tìm kiếm một câu trả lời đơn giản như vậy, cảm ơn!
Adam Waite

1
Swift 3: self.navigationController? .PopToRootViewController (hoạt hình: true);
dianakarenms

Chính xác những gì tôi đang tìm kiếm!
Canucklesandwich

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

objectAtIndex: 1 -> bạn có thể chuyển bất kỳ chỉ mục nào bạn muốn bật tới


Cảm ơn vì thủ thuật này, tôi chỉ sắp làm sai cách.
Linus

18

Swift 2 - xCode 7.3

Đây có thể là một tiện ích mở rộng rất hữu ích để bật 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
Điều này cần nhiều sự ủng hộ hơn .. Tôi vừa định viết phần mở rộng đó. Tôi sẽ chỉ sử dụng lời cảm ơn của bạn;)
n13

1
@ n13 sao câu này hay hơn câu trả lời của budidino?
Crashalot

1
Sử dụng tiện ích mở rộng giúp mã sạch hơn nhiều. Bạn có thể lấy câu trả lời của budidino và thực hiện một phần mở rộng của nó nhưng câu trả lời này giúp bạn tiết kiệm công sức. Ngoài ra câu trả lời này kiểm tra đối với trường hợp lỗi và xử lý lỗi một cách duyên dáng (ví dụ như cố gắng để bật hơn bạn có)
N13

1
Tôi thích câu trả lời này. Khiến tôi phải suy nghĩ lại và cập nhật câu trả lời mà tôi đã đăng. Tôi đã làm cho mã của mình bật lên phiên bản cuối cùng của lớp được tìm kiếm trong mảng viewControllers vì đó có thể là hành vi mong muốn.
budidino

15

Nếu bạn chỉ muốn bật 2 cùng một lúc vì rootViewController của bạn (cách) 'sâu hơn' thì 2 bạn có thể xem xét thêm một danh mục vào UIviewController, ví dụ:

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

Nhập danh mục #import "UINavigationController+popTwice.h"ở đâu đó trong triển khai của bạn và sử dụng dòng mã này để bật 2 bộ điều khiển cùng một lúc:

[self.navigationController popTwoViewControllersAnimated:YES];

điều đó không tuyệt phải không? :)


6
điều gì sẽ xảy ra nếu bạn cần bật ba chế độ xem, bạn sẽ viết "UINavigationController + popThrice.m" ??????
Gặp nhau

8
bạn có thể chỉ cần chuyển vào một tham số cho số lượng viewControllers để bật lên và bọc [self popViewControllerAnimated: NO]; trong vòng lặp for, đếm-1.
noRema

Đây không phải là cách chính xác, nếu bạn muốn tăng lên 2,3, ... bất kỳ bộ điều khiển nào xác định nó bằng vòng lặp và sau đó sử dụng [self.navigationController popToViewControllerAnimated: YES] ;. Điều này được đề cập ở trên là mã hóa rất tệ và có thể hiển thị giao diện người dùng không ổn định và trải nghiệm người dùng không tốt.
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)
    }
}

Sau đó sử dụng phương pháp này

self.popViewControllerss(popViews: 2)

Tốt, Điều tôi đang tìm kiếm. Cảm ơn.
maddysan

6

Bạn cũng có thể thử cái này: -

[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

Trong Swift 3 , bạn có thể bật một, hai hoặc nhiều bộ điều khiển chế độ xem từ bộ điều khiển điều hướng như vậy

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

Đây FromWhereYouWantToGoController là bộ điều khiển đích. Hy vọng nó giúp.


3

Bạn có thể chuyển bộ điều khiển chế độ xem ban đầu (bộ điều khiển bạn muốn quay lại) và sau đó gọi dòng này trong chế độ xem cuối cùng:

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

L.


3

Tôi không thấy câu trả lời này ở đây. Nếu bạn chỉ muốn bật một vài (không phải tất cả các cách đến thư mục gốc), bạn chỉ có thể lặp lại qua self.navigationController.viewControllers kiểm tra các loại lớp hoặc nếu bạn có tham chiếu, hãy sử dụng:

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

2

bạn có thể quay lại bộ điều khiển chế độ xem gốc

[self.navigationController popToRootViewControllerAnimated:YES];

hoặc nếu chế độ xem bạn muốn bật lên không phải là chế độ đầu tiên, bạn sẽ cần bật lại trong chế độ xem của chế độ xem trước đó của mình


2

Đây là một chức năng nhỏ mà tôi đang sử dụng để quay lại 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

Phiên bản Swift kể từ (Swift 1.2 / Xcode 6.3.1) xuất hiện hai lần trở lên

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

hoặc là

 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

Bạn có thể sử dụng ngăn xếp của UIViewControllers. 1. Tìm nạp mảng của tất cả các viewControllers trong ngăn xếp. 2. Lặp lại toàn bộ mảng và tìm viewController mong muốn
bằng cách khớp với loại lớp. 3. Bật 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

Sử dụng tiện ích mở rộng UINavigationController đơn giản :

extension UINavigationController {
    func popViewControllers(_ count: Int) {
        guard viewControllers.count > count else { return }
        popToViewController(viewControllers[viewControllers.count - count - 1], animated: true)
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.