2009-11-29 95 views
121

我正在努力尋找解決此問題的良好解決方案。在視圖控制器的-viewWillDisappear:方法中,我需要找到一種方法來確定是因爲視圖控制器被推到導航控制器的堆棧上,還是因爲視圖控制器因彈出而消失。viewWillDisappear:確定是否正在彈出視圖控制器或正在顯示子視圖控制器

目前我正在設置標誌,如isShowingChildViewController,但它變得相當複雜。我想我可以檢測到的唯一方法是在-dealloc方法中。

回答

219

您可以使用以下方法。

- (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"); 
    } 
} 

這是當然的,可能的,因爲的UINavigationController的視圖控制器堆棧(通過viewControllers屬性公開)已經由該viewWillDisappear被調用的時候進行更新。

+2

完美!我不知道爲什麼我沒有想到這一點!我想我不認爲堆棧會被調用,直到消失方法被調用!謝謝:-) – 2009-11-29 21:56:47

+1

我剛剛一直在嘗試執行相同的事情,但在'viewWillAppear',它似乎是否視圖控制器被推出或被推出的東西被揭示,viewControllers數組是相同的雙向!有任何想法嗎? – 2009-11-30 11:49:18

+0

我還應該注意到視圖控制器在應用程序的整個生命週期中是持久的,所以我不能在'viewDidLoad'上執行我的操作,因爲它只被調用一次!嗯,棘手的一個! – 2009-11-30 11:56:02

-1

我假設你的意思是說,當你說推入堆棧時,你的視圖會通過推動一個新視圖在導航控制器的棧中向下移動。我建議使用viewDidUnload方法添加一條NSLog語句來向控制檯寫入內容,以便您可以看到發生了什麼,您可能需要將NSLog添加到viewWillDissappeer

16

如果你只是想知道你的視圖是否被彈出,我剛剛發現self.navigationControllernilviewDidDisappear,當它從堆棧的控制器中刪除。所以這是一個簡單的替代測試。我很驚訝沒有導航控制器協議來註冊一個視圖控制器來通知流行音樂,你不能使用UINavigationControllerDelegate,因爲這實際上是真正的顯示工作。 )

-1

這裏是完成同樣的事情sbrocket的回答類別:

標題:

#import <UIKit/UIKit.h> 

@interface UIViewController (isBeingPopped) 

- (BOOL) isBeingPopped; 

@end 

來源:

#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

我認爲最簡單的方法是:

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

斯威夫特:

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

截至iOS 5這是答案,也許還檢查isBeingDismissed – d370urn3ur 2013-12-23 10:52:13

+3

對於iOS7我必須再次檢查[self.navigationController.viewControllers indexOfObject:self] == NSNotFound,因爲背景應用程序也將通過此測試,但不會刪除自己從導航堆棧。 – 2014-02-28 10:07:45

+0

整潔乾淨! – AsifHabib 2015-02-20 08:17:57

0

這個問題是很老,但我認爲這是偶然,所以我要發佈最佳實踐(afaik)

你可以做

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

有很多降級答案,我認爲公平地提一下爲什麼要降級答案。 – Jiraheta 2016-08-17 16:16:17

0

這適用於iOS7,不知道它是否適用於任何其他的。據我所知,在viewDidDisappear視圖已經彈出。這意味着當您查詢self.navigationController.viewControllers時,您將獲得nil。所以只需檢查一下是否爲零。

TL; DR

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

塞格斯可以是在IOS處理這個問題6+一個非常有效的方法。如果您在Interface Builder中給出了特定的Segue標識符,您可以在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

在夫特:

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

    super.viewWillDisappear(animated) 

} 
+0

確保使用as!而不是像 – dfmuir 2015-05-13 13:42:56

52

從蘋果公司在UIViewController.h文檔:

「這四種方法可以以視圖控制器的外觀用於 回調以確定它是否是被呈現,解散或添加 或作爲子視圖控制器被移除。例如,視圖控制器 可以檢查它是否正在消失b因爲它被解僱或彈出 通過詢問自己在其viewWillDisappear:方法通過檢查 表達式([self isBeingDismissed] || [自 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);

所以,是的,唯一記載的方式來做到這一點是通過以下方式:

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

斯威夫特3版本:

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

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

這是適當的答案。 – mattyohe 2015-11-24 16:26:08

3

斯威夫特3

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

我發現蘋果的這個文件是很難理解的。此擴展程序有助於查看每個導航的狀態。

extension UIViewController { 
    public func printTransitionStates() { 
     print("isBeingPresented=\(isBeingPresented)") 
     print("isBeingDismissed=\(isBeingDismissed)") 
     print("isMovingToParentViewController=\(isMovingToParentViewController)") 
     print("isMovingFromParentViewController=\(isMovingFromParentViewController)") 
    } 
} 
相關問題