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


当前回答

我的偏好是在导航控制器中覆盖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,因为它会导致自定义设置的问题。

其他回答

这就是我的解

extension UINavigationController: UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        if let shouldBlock = self.topViewController?.shouldPopFromNavigation() {
            return shouldBlock
        }
        return true
    }
}

extension UIViewController {
    @objc func shouldPopFromNavigation() -> Bool {
        return true
    }
}

在你的视图控制器中,你可以这样处理:

@objc override func shouldPopFromNavigation() -> Bool {
        // Your dialog, example UIAlertViewController or whatever you want
        return false
    }

试试这个。

self.navigationItem.leftBarButtonItem?.target = "methodname"
func methodname ( ) {            
  //    enter code here
}

这个也试试。

override func viewWillAppear(animated: Bool) {
  //empty your array
}

这并不像我们想象的那么难。只需要为UIButton创建一个背景颜色清晰的框架,为按钮分配动作,并放置在导航栏后退按钮上。最后在使用后取下按钮。

这是Swift 3 用UIImage代替UIButton的示例代码

override func viewDidLoad() {
    super.viewDidLoad()
    let imageView = UIImageView()
    imageView.backgroundColor = UIColor.clear
    imageView.frame = CGRect(x:0,y:0,width:2*(self.navigationController?.navigationBar.bounds.height)!,height:(self.navigationController?.navigationBar.bounds.height)!)
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(back(sender:)))
    imageView.isUserInteractionEnabled = true
    imageView.addGestureRecognizer(tapGestureRecognizer)
    imageView.tag = 1
    self.navigationController?.navigationBar.addSubview(imageView)
    }

编写需要执行的代码

func back(sender: UIBarButtonItem) {

    // Perform your custom actions}
    _ = self.navigationController?.popViewController(animated: true)

    }

执行操作后删除子视图

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

    for view in (self.navigationController?.navigationBar.subviews)!{
        if view.tag == 1 {
            view.removeFromSuperview()
        }
    }

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

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

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

你可以在视图控制器中做一些事情

override func navigationShouldPopOnBackButton() -> Bool {
    self.backAction() //Your action you want to perform.
    return true
}

完整回答使用 当导航条上的“后退”按钮被按下时进行检测