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


当前回答

在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。

其他回答

这并不像我们想象的那么难。只需要为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()
        }
    }

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

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

在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。

我通过以下方法做到了这一点:

斯威夫特3

override func didMoveToParentViewController(parent: UIViewController?) {
   super.didMoveToParentViewController(parent)

   if parent == nil {
      println("Back Button pressed.")
      delegate?.goingBack()
   }           
}

斯威夫特4

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

    if parent == nil {
        debugPrint("Back Button pressed.")
    }
}

不需要自定义后退按钮。

在离开电流控制器之前,我需要显示警报。所以我是这样做的:

添加扩展UINavigationController与UINavigationBarDelegate 添加选择器到你的控制器导航

它的工作)

extension UINavigationController: UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        if let items = navigationBar.items, viewControllers.count < items.count {
            return true
        }

        let clientInfoVC = topViewController as? ClientInfoVC
        if clientInfoVC?.responds(to: #selector(clientInfoVC?.navigationShouldPopOnBack)) ?? false {
            clientInfoVC?.navigationShouldPopOnBack(completion: { isAllowPop in
                if isAllowPop {
                    DispatchQueue.main.async {
                        self.popViewController(animated: true)
                    }
                }
            })
        }

        DispatchQueue.main.async {
            self.popViewController(animated: true)
        }

        return false
    }
}

@objc func navigationShouldPopOnBack(completion: @escaping (Bool) -> ()) {
        let ok = UIAlertAction(title: R.string.alert.actionOk(), style: .default) { _ in
            completion(true)
        }
        let cancel = UIAlertAction(title: R.string.alert.actionCancel(), style: .cancel) { _ in
            completion(false)
        }
        let alertController = UIAlertController(title: "", message: R.string.alert.contractMessage(), preferredStyle: .alert)
        alertController.addAction(ok)
        alertController.addAction(cancel)
        present(alertController, animated: true, completion: nil)
    }