我需要执行一个动作(清空一个数组),当UINavigationController的后退按钮被按下,而按钮仍然导致堆栈上的前一个ViewController出现。我如何使用swift来实现这一点?


当前回答

在我的例子中,viewWillDisappear效果最好。但在某些情况下,必须修改之前的视图控制器。所以这是我的解决方案访问之前的视图控制器,它在Swift 4中工作:

override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if isMovingFromParentViewController {
            if let viewControllers = self.navigationController?.viewControllers {
                if (viewControllers.count >= 1) {
                    let previousViewController = viewControllers[viewControllers.count-1] as! NameOfDestinationViewController
                    // whatever you want to do
                    previousViewController.callOrModifySomething()
                }
            }
        }
    }

其他回答

我的偏好是在导航控制器中覆盖popViewController。这样做的好处是:

你的应用程序保持默认的后退按钮外观和动画,你不需要管理它。如果用户在手机上设置了大号文本,这尤其有用,因为默认的后退按钮会根据用户的设置增加或减少大小。 你可以完全停止视图弹出,不像使用viewWillDisappear。

首先,创建一个自定义导航控制器类(并确保将其分配给故事板中的导航控制器或任何创建导航控制器的地方):

class NavControllerWithBackButtonOverride: UINavigationController {

    var backButtonOverride: (() -> Void)? = nil

    override func popViewController(animated: Bool) -> UIViewController? {

        if backButtonOverride != nil {
            //if anything is assigned to the backButtonOverride the override will run
            self.backButtonOverride!()
            return nil
        } else {
            //otherwise the default popViewController will run
            return super.popViewController(animated: animated)
        }
    }
}

然后通过给backButtonOverride变量赋值,在视图控制器中启用/禁用重载:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.enableCustomBackButton()
}

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

/**
 Custom Back Button
 */

func customBackButtonAction() {
    print("DO THIS INSTEAD")
}

func enableCustomBackButton() {
    if let nav = self.navigationController as? NavControllerWithBackButtonOverride {
        nav.backButtonOverride = { self.customBackButtonAction() }
        nav.interactivePopGestureRecognizer?.isEnabled = false
    }    
}

func disableCustomBackButton() {
    if let nav = self.navigationController as? NavControllerWithBackButtonOverride {
    nav.backButtonOverride = nil
    nav.interactivePopGestureRecognizer?.isEnabled = true
    }
}

注意:我还禁用了interactivePopGestureRecognizer,因为它会导致自定义设置的问题。

NO

override func willMove(父控件:UIViewController?) {}

即使你在segue到覆盖这个方法的视图控制器,这个也会被调用。其中,检查parent是否为nil或not不是确保移动回正确的UIViewController的精确方法。为了准确地确定UINavigationController是否正确地导航回呈现当前的UIViewController,你将需要遵守UINavigationControllerDelegate协议。

YES

注意:MyViewController只是你想要检测返回的UIViewController的名称。

1)在你的文件顶部添加UINavigationControllerDelegate。

class MyViewController: UIViewController, UINavigationControllerDelegate {

2)添加一个属性到你的类,它将跟踪你正在segue的UIViewController。

class MyViewController: UIViewController, UINavigationControllerDelegate {

var previousViewController:UIViewController

3)在MyViewController的viewDidLoad方法中为你的UINavigationController分配self作为委托。

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.delegate = self
}

3)在你segue之前,将之前的UIViewController分配为这个属性。

// In previous UIViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "YourSegueID" {
        if let nextViewController = segue.destination as? MyViewController {
            nextViewController.previousViewController = self
        }
    }
}

4)并遵循UINavigationControllerDelegate的MyViewController中的一个方法

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
    if viewController == self.previousViewController {
        // You are going back
    }
}
override func willMove(toParent parent: UIViewController?)
{
    super.willMove(toParent: parent)
    if parent == nil
    {
        print("This VC is 'will' be popped. i.e. the back button was pressed.")
    }
}

只需control +拖动栏项到func下面。魅力工作

@IBAction func done(sender: AnyObject) {
    if((self.presentingViewController) != nil){
        self.dismiss(animated: false, completion: nil)
        print("done")
    }
}

斯威夫特3:

override func didMove(toParentViewController parent: UIViewController?) {
    super.didMove(toParentViewController: parent)

    if parent == nil{
        print("Back button was clicked")
    }
}