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


当前回答

如果你想有后退按钮和后退箭头,你可以使用下面的图片和代码

backArrow.png backArrow@2x.png backArrow@3x.png

override func viewDidLoad() {
    super.viewDidLoad()
    let customBackButton = UIBarButtonItem(image: UIImage(named: "backArrow") , style: .plain, target: self, action: #selector(backAction(sender:)))
    customBackButton.imageInsets = UIEdgeInsets(top: 2, left: -8, bottom: 0, right: 0)
    navigationItem.leftBarButtonItem = customBackButton
}

func backAction(sender: UIBarButtonItem) {
    // custom actions here
    navigationController?.popViewController(animated: true)
}

其他回答

对于Swift 5,我们可以检查它在视图中是否会消失

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

    if self.isMovingFromParent {
        delegate?.passValue(clickedImage: selectedImage)
    }
}

在Swift 5和Xcode 10.2中

请不要添加自定义栏按钮项,使用默认行为。

不需要viewWillDisappear,不需要自定义BarButtonItem等…

最好是检测VC何时从其父对象中移除。

使用这两个函数中的任意一个

override func willMove(toParent parent: UIViewController?) {
    super.willMove(toParent: parent)
    if parent == nil {
        callStatusDelegate?.backButtonClicked()//Here write your code
    }
}

override func didMove(toParent parent: UIViewController?) {
    super.didMove(toParent: parent)
    if parent == nil {
        callStatusDelegate?.backButtonClicked()//Here write your code
    }
}

如果你想停止返回按钮的默认行为,然后添加自定义BarButtonItem。

这是我自己解决问题的方法

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationItem.leftBarButtonItem?.action = #selector(self.back(sender:))
    self.navigationItem.leftBarButtonItem?.target = self
}

@objc func back(sender: UIBarButtonItem) {

}

如果你正在使用navigationController,那么将UINavigationControllerDelegate协议添加到类中,并添加delegate方法,如下所示:

class ViewController:UINavigationControllerDelegate {

    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController,
animated: Bool) {
        if viewController === self {
            // do here what you want
        }
    }
}

每当导航控制器滑到新屏幕时,就调用此方法。如果返回按钮被按下,新的视图控制器就是ViewController本身。

你可以子类化UINavigationController并重写popViewController(animated: Bool)。除了能够在那里执行一些代码,你还可以防止用户完全返回,例如提示保存或丢弃他当前的工作。

示例实现,其中您可以设置popHandler,由推送的控制器设置/清除。

class NavigationController: UINavigationController
{
    var popHandler: (() -> Bool)?

    override func popViewController(animated: Bool) -> UIViewController?
    {
        guard self.popHandler?() != false else
        {
            return nil
        }
        self.popHandler = nil
        return super.popViewController(animated: animated)
    }
}

以及来自跟踪未保存工作的推送控制器的示例使用情况。

let hasUnsavedWork: Bool = // ...
(self.navigationController as! NavigationController).popHandler = hasUnsavedWork ?
    {
        // Prompt saving work here with an alert

        return false // Prevent pop until as user choses to save or discard

    } : nil // No unsaved work, we clear popHandler to let it pop normally

作为一个很好的触摸,这也将被interactivePopGestureRecognizer调用,当用户试图返回使用滑动手势。