2009-11-29 31 views
121

Tôi đang cố gắng tìm một giải pháp tốt cho vấn đề này. Trong phương thức -viewWillDisappear: của bộ điều khiển chế độ xem, tôi cần tìm cách xác định xem đó là do bộ điều khiển chế độ xem đang được đẩy lên ngăn xếp của trình điều khiển điều hướng hay là do bộ điều khiển chế độ xem biến mất vì nó đã bị xuất hiện.viewWillDisappear: Xác định xem bộ điều khiển xem có bị xuất hiện hay đang hiển thị bộ điều khiển phụ xem

Hiện tại tôi đang đặt cờ như isShowingChildViewController nhưng việc này trở nên khá phức tạp. Cách duy nhất tôi nghĩ rằng tôi có thể phát hiện nó là trong phương pháp -dealloc.

Trả lời

219

Bạn có thể sử dụng các mục sau.

- (void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 
    NSArray *viewControllers = self.navigationController.viewControllers; 
    if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) { 
    // View is disappearing because a new view controller was pushed onto the stack 
    NSLog(@"New view controller was pushed"); 
    } else if ([viewControllers indexOfObject:self] == NSNotFound) { 
    // View is disappearing because it was popped from the stack 
    NSLog(@"View controller was popped"); 
    } 
} 

Đây là, tất nhiên, có thể vì chồng xem điều khiển của UINavigationController (tiếp xúc thông qua thuộc tính viewControllers) đã được cập nhật bởi thời gian mà viewWillDisappear được gọi.

+2

Hoàn hảo! Tôi không biết tại sao tôi không nghĩ về điều đó! Tôi đoán tôi đã không nghĩ rằng ngăn xếp sẽ được thay đổi cho đến khi các phương pháp biến mất đã được gọi! Cảm ơn :-) –

+1

Tôi vừa cố gắng thực hiện điều tương tự nhưng trong 'viewWillAppear' và có vẻ như liệu bộ điều khiển xem có đang bị tiết lộ bởi nó bị đẩy hoặc một thứ gì đó ở trên nó bị xuất hiện không, mảng viewControllers là giống nhau cả hai hướng! Ý tưởng nào? –

+0

Tôi cũng nên lưu ý rằng trình điều khiển chế độ xem liên tục trong suốt thời gian của ứng dụng nên tôi không thể thực hiện tác vụ của mình trên 'viewDidLoad' vì nó chỉ được gọi một lần! Hmm, khó khăn! –

-1

Tôi giả sử bạn có nghĩa là chế độ xem của bạn đang được di chuyển xuống ngăn xếp của trình điều khiển điều hướng bằng cách đẩy chế độ xem mới khi bạn nói được đẩy lên ngăn xếp. Tôi khuyên bạn nên sử dụng phương pháp viewDidUnload để thêm tuyên bố NSLog để viết điều gì đó vào bảng điều khiển để bạn có thể xem điều gì đang diễn ra, bạn có thể muốn thêm NSLog vào viewWillDissappeer.

16

Nếu bạn chỉ muốn biết liệu chế độ xem của bạn có bị xuất hiện hay không, tôi vừa phát hiện ra rằng self.navigationControllernil trong viewDidDisappear, khi nó bị xóa khỏi bộ điều khiển. Vì vậy, đó là một thử nghiệm thay thế đơn giản.

(Điều này tôi khám phá sau khi thử tất cả các loại khác nhau) Tôi ngạc nhiên không có giao thức điều khiển điều hướng để đăng ký một bộ điều khiển xem được thông báo trên pops.Bạn không thể sử dụng UINavigationControllerDelegate vì nó thực sự làm công việc hiển thị thực sự.)

-1

Dưới đây là một phạm trù để thực hiện được điều tương tự như câu trả lời của sbrocket:

Tiêu đề:

#import <UIKit/UIKit.h> 

@interface UIViewController (isBeingPopped) 

- (BOOL) isBeingPopped; 

@end 

Nguồn:

#import "UIViewController+isBeingPopped.h" 

@implementation UIViewController (isBeingPopped) 

- (BOOL) isBeingPopped { 
    NSArray *viewControllers = self.navigationController.viewControllers; 
    if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) { 
     return NO; 
    } else if ([viewControllers indexOfObject:self] == NSNotFound) { 
     return YES; 
    } 
    return NO; 
} 

@end 
116

Tôi nghĩ rằng cách dễ nhất là:

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
    if ([self isMovingFromParentViewController]) 
    { 
     NSLog(@"View controller was popped"); 
    } 
    else 
    { 
     NSLog(@"New view controller was pushed"); 
    } 
} 

Swift:

override func viewWillDisappear(animated: Bool) 
{ 
    super.viewWillDisappear(animated) 
    if isMovingFromParentViewController 
    { 
     print("View controller was popped") 
    } 
    else 
    { 
     print("New view controller was pushed") 
    } 
} 
+0

Kể từ iOS 5, đây là câu trả lời, có thể cũng kiểm tra isBeingDismissed – d370urn3ur

+3

Đối với iOS7, tôi phải kiểm tra [self.navigationController.viewControllers indexOfObject: self] == NSNotFound một lần nữa vì nền ứng dụng cũng sẽ vượt qua bài kiểm tra này nhưng sẽ không tự xóa từ ngăn xếp điều hướng. –

+0

Gọn gàng và sạch sẽ! – AsifHabib

0

Câu hỏi này là khá cũ nhưng tôi thấy nó một cách tình cờ vì vậy tôi muốn gửi thực hành tốt nhất (afaik)

bạn chỉ có thể thực hiện

if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound) 
// view controller popped 
} 
+0

Có rất nhiều câu trả lời hạ cấp, tôi nghĩ rằng nó sẽ là công bằng để đề cập đến lý do tại sao bạn sẽ hạ cấp câu trả lời. – Jiraheta

0

này áp dụng cho iOS7, không có ý tưởng nếu nó áp dụng cho bất kỳ những người khác. Từ những gì tôi biết, trong viewDidDisappear chế độ xem đã được xuất hiện. Điều này có nghĩa là khi bạn truy vấn self.navigationController.viewControllers, bạn sẽ nhận được nil. Vì vậy, chỉ cần kiểm tra nếu đó là số không.

TL; DR

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 
    if (self.navigationController.viewControllers == nil) { 
     // It has been popped! 
     NSLog(@"Popped and Gone"); 
    } 
} 
0

Segues có thể là một cách rất hiệu quả xử lý vấn đề này trong iOS 6+. Nếu bạn đã đưa ra một phân biệt cụ thể trong Trình tạo giao diện, bạn có thể kiểm tra nó trong prepareForSegue.

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([segue.identifier isEqualToString:@"LoginSegue"]) { 
     NSLog(@"Push"); 
     // Do something specific here, or set a BOOL indicating 
     // a push has occurred that will be checked later 
    } 
} 
5

Trong Swift:

override func viewWillDisappear(animated: Bool) { 
    if let navigationController = self.navigationController { 
     if !contains(navigationController.viewControllers as! Array<UIViewController>, self) { 
     } 
    } 

    super.viewWillDisappear(animated) 

} 
+0

Đảm bảo sử dụng như! thay vì là – dfmuir

52

Từ Tài liệu của Apple trong UIViewController.h:

"Bốn phương pháp có thể được sử dụng trong xuất hiện một cái nhìn khiển của callbacks để xác định xem nó là được trình bày, loại bỏ hoặc thêm hoặc bị xóa dưới dạng bộ điều khiển xem con. Ví dụ: bộ điều khiển chế độ xem có thể kiểm tra xem nó có đang biến mất hay không ecause nó đã bị loại bỏ hoặc popped bằng cách tự hỏi trong phương thức viewWillDisappear: bằng cách kiểm tra biểu thức ([self isBeingDismissed] || [Tự isMovingFromParentViewController]) "

- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);

- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);

Vì vậy, có, cách duy nhất ghi lại để làm điều này là theo cách sau:.

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
    if ([self isBeingDismissed] || [self isMovingFromParentViewController]) { 
    } 
} 

Swift 3 phiên bản:

override func viewWillDisappear(_ animated: Bool) { 
    super.viewWillDisappear(animated) 

    if self.isBeingDismissed || self.isMovingFromParentViewController { 
    } 
} 
+1

Đây là câu trả lời thích hợp. – mattyohe

3

Swift 3

override func viewWillDisappear(_ animated: Bool) 
    { 
     super.viewWillDisappear(animated) 
     if self.isMovingFromParentViewController 
     { 
      //View Controller Popped 
     } 
     else 
     { 
      //New view controller pushed 
     } 
    } 
1

Tôi tìm thấy tài liệu của Apple về vấn đề này là khó hiểu. Tiện ích này giúp xem trạng thái tại mỗi điều hướng.

extension UIViewController { 
    public func printTransitionStates() { 
     print("isBeingPresented=\(isBeingPresented)") 
     print("isBeingDismissed=\(isBeingDismissed)") 
     print("isMovingToParentViewController=\(isMovingToParentViewController)") 
     print("isMovingFromParentViewController=\(isMovingFromParentViewController)") 
    } 
} 
Các vấn đề liên quan