簡體   English   中英

iOS如何在彈出頂視圖控制器時以編程方式檢測?

[英]iOS how to detect programmatically when top view controller is popped?

假設我有一個帶有2個視圖控制器的導航控制器堆棧:VC2位於頂部,VC1位於底層。 我可以在VC1中包含哪些代碼來檢測VC2剛剛從堆棧中彈出?

由於我試圖從VC1的代碼中檢測到VC2的彈出,似乎像viewWillAppearviewDidAppear這樣的東西不起作用,因為這些方法每次顯示VC1時都會觸發,包括它首次被壓入堆棧時。

編輯:我原來的問題似乎不太清楚。 這是我正在嘗試做的事情:確定VC1何時顯示是由於VC2從堆棧頂部彈出。 這是我不想做的事情:確定VC1由於被推到堆棧頂部而顯示的時間。 我需要某種方法來檢測第一個動作但不是第二個動作。

注意:我並不特別關心VC2,它可以是從堆棧彈出的任何數量的其他VC,我關心的是當VC1再次成為堆棧頂部時由於其他一些VC開始彈出最佳。

iOS 5引入了兩種新方法來處理這種情況。 你要找的是-[UIViewController isMovingToParentViewController] 來自文檔

isMovingToParentViewController

返回一個布爾值,指示視圖控制器正在添加到父級。

- (BOOL)isMovingToParentViewController

回報價值
如果視圖控制器正在出現,則為YES,因為它已添加為容器視圖控制器的子級,否則為NO。

討論
僅當從以下方法內部調用時,此方法才返回YES:

-viewWillAppear:
-viewDidAppear:

在你的情況下,你可以實現-viewWillAppear:像這樣:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (self.isMovingToParentViewController == NO)
    {
        // we're already on the navigation stack
        // another controller must have been popped off
    }
}

編輯:這里有一個微妙的語義差異 - 你是否對VC2特別是從堆棧彈出的事實感興趣,或者你是否希望每次VC1因任何控制器彈出而被泄露時都會收到通知? 在前一種情況下,授權是一種更好的解決方案。 如果您從未打算重用VC2,那么對VC1的直接弱引用也可以起作用。

編輯2:我通過反轉邏輯並且不提前返回使示例更加明確。

isMovingTo / FromParentViewController不適用於推送和彈出導航控制器堆棧。

這是一種可行的方法(不使用委托),但它可能只是iOS 7+。

UIViewController *fromViewController = [[[self navigationController] transitionCoordinator] viewControllerForKey:UITransitionContextFromViewControllerKey];

if ([[self.navigationController viewControllers] containsObject:fromViewController])
{
    //we're being pushed onto the nav controller stack.  Make sure to fetch data.
} else {
    //Something is being popped and we are being revealed
}

在我的情況下,使用委托意味着讓視圖控制器的行為與擁有導航堆棧的委托更緊密地耦合,我想要一個更獨立的解決方案。 這有效。

你可以采用的一種方法是為VC2聲明一個委托協議,如下所示:

在VC1.h

@interface VC1 : UIViewController <VC2Delegate> {
...
}

在VC1.m中

-(void)showVC2 {
    VC2 *vc2 = [[VC2 alloc] init];
    vc2.delegate = self;
    [self.navigationController pushViewController:vc2 animated:YES];
}

-(void)VC2DidPop {
    // Do whatever in response to VC2 being popped off the nav controller
}

在VC2.h中

@protocol VC2Delegate <NSObject>
-(void)VC2DidPop;
@end

@interface VC2 : UIViewController {

    id<VC2Delegate> delegate;
}

@property (nonatomic, assign) id delegate;

...

@end

VC2.m

-(void)viewDidUnload {
    [super viewDidUnload];
    [self.delegate VC2DidPop];
}

有一個關於協議和代表的基礎知識的好文章在這里

您還可以在正在彈出的視圖控制器中進行檢測

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if ([self isMovingFromParentViewController]) {
        ....
    }
}

這對我有用

UIViewController *fromViewController = [[[self navigationController] transitionCoordinator] viewControllerForKey:UITransitionContextFromViewControllerKey];
if (![[self.navigationController viewControllers] containsObject:fromViewController] && !self.presentedViewController)
{
  //Something is being popped and we are being revealed 
}

你有什么具體的嘗試?

如果您正在嘗試檢測VC1即將顯示,則答案應該對您有所幫助。 使用UINavigationControllerDelegate

如果你試圖檢測VC2即將被隱藏,我只會使用VC2的viewWillDisappear: .

是的,在VC1中,您可以檢查VC2是否彈出。 UINavigationController有一個方法viewControllers ,它將返回推送的控制器數組,這些控制器位於堆棧中(即已被推送)。

所以你通過比較類迭代循環。 如果VC2在那里,將匹配,否則不匹配。

迅捷3

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if self.isMovingToParentViewController {
            print("View is moving to ParentViewControll")
        }
}

我得到了相同的情況,但有一些更具體的用例。 在我的情況下,我們想確定當用戶點擊VC2的后退按鈕時是否出現/顯示VC1,其中VC2被推送到VC​​1上的navigationController上。

所以我根據自己的需要使用snarshad的答案來定制。 這是VC1在swift 3中viewDidAppear中的代碼。

// VC1: ParentViewController
// VC2: ChildViewController

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

        if let transitionCoordinator = navigationController?.transitionCoordinator,
            let fromVC = transitionCoordinator.viewController(forKey: UITransitionContextViewControllerKey.from),
            let toVC = transitionCoordinator.viewController(forKey: UITransitionContextViewControllerKey.to),
            fromVC is ChildViewController,
            toVC is ParentViewController {

            print("Back button pressed on ChildViewController, and as a result ParentViewController appeared")
        }
    }

您可以為VC2添加NSNotification的觀察者,特別是JUST。

// pasing the "VC2" here will tell the notification to only listen for notification from
// VC2 rather than every single other objects
[[NSNotitificationCenter defaultCenter] addObserver:self selector:@selector(doSomething:) object:VC2];

現在你的VC2視圖將消失,你可以發布通知:

-(void)viewWillDisappear
{
    [[NSNotificationCenter defaultCenter] postNotificationNamed:@"notif_dismissingVC2" object:nil];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM