我需要知道我的视图控制器何时将从导航堆栈中弹出,以便我可以执行操作。
我不能使用 -viewWillDisappear,因为当视图控制器出于任何原因移出屏幕时会调用它(比如将新的视图控制器推到顶部)。
我特别需要知道控制器何时会自行弹出。
任何想法都会很棒,在此先感谢。
我需要知道我的视图控制器何时将从导航堆栈中弹出,以便我可以执行操作。
我不能使用 -viewWillDisappear,因为当视图控制器出于任何原因移出屏幕时会调用它(比如将新的视图控制器推到顶部)。
我特别需要知道控制器何时会自行弹出。
任何想法都会很棒,在此先感谢。
覆盖viewWillDisappear
提供的 VC 中的方法,然后检查isMovingFromParentViewController
覆盖中的标志并执行特定逻辑。就我而言,我隐藏了导航控制器工具栏。仍然需要您介绍的 VC 了解它是被推动的,尽管它并不完美。
幸运的是,当 viewWillDisappear 方法被调用时,viewController 已经从堆栈中移除了,所以我们知道 viewController 正在弹出,因为它不再在self.navigationController.viewControllers中
斯威夫特 4
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let nav = self.navigationController {
let isPopping = !nav.viewControllers.contains(self)
if isPopping {
// popping off nav
} else {
// on nav, not popping off (pushing past, being presented over, etc.)
}
} else {
// not on nav at all
}
}
原始代码
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if ((self.navigationController) &&
(![self.navigationController.viewControllers containsObject:self])) {
NSLog(@"I've been popped!");
}
}
尝试在您的自定义子类中覆盖willMoveToParentViewController:
(而不是) .viewWillDisappear:
UIViewController
在从容器视图控制器中添加或删除视图控制器之前调用。
- (void)willMoveToParentViewController:(UIViewController *)parent
{
[super willMoveToParentViewController:parent];
if (!parent) {
// `self` is about to get popped.
}
}
我认为没有明确的消息,但您可以继承 UINavigationController 并覆盖 - popViewControllerAnimated(尽管我自己之前没有尝试过)。
或者,如果没有其他对视图控制器的引用,您可以添加到它的-dealloc 吗?
这对我有用。
- (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,但我没有调用该函数 :((不知道为什么,可能是因为我所有的 VC 都是 UITableViewController)。Alex 的建议工作正常,但如果您的导航控制器显示在更多选项卡。在这种情况下,您的导航控制器的所有 VC 的导航控制器都为 UIMoreNavigationController,而不是您已子类化的导航控制器,因此当 VC 即将弹出时,导航不会通知您。
最后,我解决了问题使用 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];
}
这个想法是在弹出时,视图控制器的 navigationController 设置为 nil。因此,如果视图要消失,并且它不再有一个导航控制器,我得出的结论是它被弹出了。(在其他情况下可能不起作用)。
不能保证 viewWillDisappear 会在弹出时被调用,因为文档中没有提到它。当视图是顶视图和顶视图下方时,我尝试了它 - 它在两者中都有效。
祝你好运,奥德。
子类UINavigationController
和覆盖popViewController
:
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
}
}
你可以使用这个:
if(self.isMovingToParentViewController)
{
NSLog(@"Pushed");
}
else
{
NSLog(@"Popped");
}
也许你可以使用 UINavigationBarDelegate 的 navigationBar:shouldPopItem 协议方法。
尝试在 viewwilldisappear 中进行此检查 if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound) { //这个视图的弹出已经发生。}
我有时还需要防止弹出,所以对我来说最好的答案是由 Orkhan Alikhanov 写的。但是因为没有设置delegate所以不起作用,所以我做了最终版本:
import UIKit
class CustomActionsNavigationController: UINavigationController,
UIGestureRecognizerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
interactivePopGestureRecognizer?.delegate = self
}
override func popViewController(animated: Bool) -> UIViewController? {
if let delegate = topViewController as? CustomActionsNavigationControllerDelegate {
guard delegate.shouldPop() else { 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
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
if let delegate = topViewController as? CustomActionsNavigationControllerDelegate {
if !delegate.shouldPop() {
return false
}
}
// This if statement prevents navigation controller to pop when there is only one view controller
if viewControllers.count == 1 {
return false
}
return true
}
}
protocol CustomActionsNavigationControllerDelegate {
func shouldPop() -> Bool
}
更新
我添加了viewControllers.count == 1
案例,因为如果堆栈中有一个控制器并且用户做出手势,它将冻结您的应用程序的 UI。
您可以观察通知:
- (void)viewDidLoad{
[super viewDidLoad];
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(navigationControllerWillShowViewController:) name:@"UINavigationControllerWillShowViewControllerNotification" object:nil];
}
- (void)navigationControllerDidShowViewController:(NSNotification *)notification{
UIViewController *lastVisible = notification.userInfo[@"UINavigationControllerLastVisibleViewController"];
if(lastVisible == self){
// we are being popped
}
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
const BOOL removingFromParent = ![self.navigationController.viewControllers containsObject:self.parentViewController];
if ( removingFromParent ) {
// cleanup
}
}