52

2 つのビュー コントローラーを備えたナビゲーション コントローラー スタックがあるとします。VC2 が上にあり、VC1 が下にあります。VC2 がスタックからポップされたことを検出する VC1 に含めることができるコードはありますか?

VC1 のコード内から VC2 のポップを検出しようとしているので、viewWillAppearviewDidAppearなどのメソッドは、最初にスタックにプッシュされたときを含め、VC1 が表示されるたびに起動するため、機能しないようです。

編集:元の質問はあまり明確ではなかったようです。これが私がやろうとしていることです: VC2 がスタックの一番上からポップされたために VC1 がいつ表示されるかを判断します。私がやろうとしていないことは次のとおりです。スタックの一番上にプッシュされたためにVC1がいつ表示されるかを判断します。最初のアクションを検出する方法が必要ですが、2 番目のアクションは検出しません。

注: VC2 については特に気にしません。スタックから取り出される他の VC の数はいくつでも構いません。上。

4

10 に答える 10

63

iOS 5 では、まさにこのタイプの状況を処理するための 2 つの新しい方法が導入されました。あなたが探しているのは-[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:ロジックを反転し、早期に返さないことで、例をより明確にしました。

于 2012-09-12T04:20:03.430 に答える
7

これにアプローチできる 1 つの方法は、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];
}

プロトコルとデリゲートの基本に関する優れた記事がここにあります。

于 2012-09-12T04:09:10.397 に答える
5

ポップされているView Controllerで検出することもできます

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

    if ([self isMovingFromParentViewController]) {
        ....
    }
}
于 2016-09-06T06:59:17.727 に答える
0

特にVC2専用のNSNotificationのオブザーバーを追加できます。

// 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];
}
于 2012-09-12T04:31:38.753 に答える
0

具体的に何をしようとしていますか?

VC1 が表示されようとしていることを検出しようとしている場合は、この回答が役に立ちます。UINavigationControllerDelegateを使用します。

VC2 が隠されようとしていることを検出しようとしている場合はviewWillDisappear:、VC2 の を使用します。

于 2012-09-12T03:52:54.157 に答える
0

私は同じ状況になりましたが、もう少し具体的なユースケースがあります。私の場合、ユーザーがVC2の戻るボタンをタップしたときにVC1が表示/表示されるかどうかを判断したかったのですが、VC2はVC1を介してnavigationControllerで押されました。

そのため、必要に応じてカスタマイズするためのsnarshadの回答の助けを借りました。viewDidAppearこれは、swift 3の VC1 のコードです。

// 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")
        }
    }
于 2017-09-08T11:02:39.573 に答える
-1

Yes, in VC1 you can check whether VC2 is popped or not. UINavigationController there is one method viewControllers which will returns the array of pushed Controllers, which are in the stack (i.e. which have been pushed).

So you iterate through loop by comparing class. If VC2 is there, will have match, otherwise not.

于 2012-09-12T04:58:55.903 に答える