UIViewControllerがナビゲーションスタックからポップされるかどうかを確認しますか?
-
22-07-2019 - |
質問
View Controllerがnavスタックからポップされようとしていることを知る必要があるので、アクションを実行できます。
-viewWillDisappearは使用できません。これは、View Controllerが何らかの理由で画面外に移動したときに呼び出されるためです(新しいView Controllerが上にプッシュされるなど)。
コントローラがいつポップされるのかを具体的に知る必要があります。
どんなアイデアでも素晴らしいと思います、事前に感謝します。
解決
これについて明示的なメッセージはないと思いますが、UINavigationControllerをサブクラス化してpopViewControllerAnimatedをオーバーライドできます(自分で試したことはありませんが)。
別の方法として、View Controllerへの他の参照がない場合、-deallocに追加できますか?
他のヒント
提示されたVCの viewWillDisappear
メソッドをオーバーライドし、オーバーライド内の isMovingFromParentViewController
フラグを確認して、特定のロジックを実行します。私の場合、Navigation Controllerのツールバーを隠しています。提示されたVCがプッシュされたことを理解する必要がありますが、完璧ではありません。
これは私のために働いています。
- (void)viewDidDisappear:(BOOL)animated
{
if (self.parentViewController == nil) {
NSLog(@"viewDidDisappear doesn't have parent so it's been popped");
//release stuff here
} else {
NSLog(@"PersonViewController view just hidden");
}
}
ここでキャッチできます。
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (viewController == YourAboutToAppearController) {
// do something
}
}
これは、新しいビューが表示される直前に発生します。まだ誰も動いていない。私はいつもasinine NavigationControllerの前で魔法をかけています。タイトルとボタンのタイトルを設定し、そこで何でもできます。
同じ問題があります。 viewDisDisappearで試しましたが、関数getがありません:((おそらく、すべてのVCがUITableViewControllerであるためかわかりません)。
Alexの提案は正常に機能しますが、ナビゲーションコントローラーが[その他]タブに表示されている場合は失敗します。この場合、navコントローラーのすべてのVCには、サブクラス化したナビゲーションコントローラーではなく、navigationControllerがUIMoreNavigationControllerとして設定されているため、VCがポップされるときにnavから通知されません。
最後に、UINavigationControllerのカテゴリで問題を解決しました。書き換えるだけです-(UIViewController *)popViewControllerAnimated:(BOOL)animated
- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
NSLog(@"UINavigationController(Magic)");
UIViewController *vc = self.topViewController;
if ([vc respondsToSelector:@selector(viewControllerWillBePopped)]) {
[vc performSelector:@selector(viewControllerWillBePopped)];
}
NSArray *vcs = self.viewControllers;
UIViewController *vcc = [vcs objectAtIndex:[vcs count] - 2];
[self popToViewController:vcc animated:YES];
return vcc;}
それは私にとってはうまくいく:D
これを試しました:
- (void) viewWillDisappear:(BOOL)animated {
// If we are disappearing because we were removed from navigation stack
if (self.navigationController == nil) {
// YOUR CODE HERE
}
[super viewWillDisappear:animated];
}
アイデアは、ポップ時にView ControllerのnavigationControllerがnilに設定されるということです。 そのため、ビューが消え、さらにnavigationControllerが含まれている場合は、ポップされたと判断しました。 (他のシナリオでは機能しない場合があります)。
viewWillDisappearは、ドキュメントに記載されていないため、ポップ時に呼び出されることを保証できません。ビューがトップビューで、トップビューの下にあるときに試しました-両方で機能しました。
頑張って、 Oded。
これを使用できます:
if(self.isMovingToParentViewController)
{
NSLog(@"Pushed");
}
else
{
NSLog(@"Popped");
}
サブクラス UINavigationController
および popViewController
のオーバーライド:
Swift 3
protocol CanPreventPopProtocol {
func shouldBePopped() -> Bool
}
class MyNavigationController: UINavigationController {
override func popViewController(animated: Bool) -> UIViewController? {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return nil
}
}
return super.popViewController(animated: animated)
}
//important to prevent UI thread from freezing
//
//if popViewController is called by gesture recognizer and prevented by returning nil
//UI will freeze after calling super.popViewController
//so that, in order to solve the problem we should not return nil from popViewController
//we interrupt the call made by gesture recognizer to popViewController through
//returning false on gestureRecognizerShouldBegin
//
//tested on iOS 9.3.2 not others
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return false
}
}
return true
}
}
おそらく、UINavigationBarDelegateのnavigationBar:shouldPopItemプロトコルメソッドを使用できます。
viewでこのチェックを行うと消えます if([self.navigationController.viewControllers indexOfObject:self] == NSNotFound){ //このビューのポップが発生しました。 }