我需要执行一个动作(清空一个数组),当UINavigationController的后退按钮被按下,而按钮仍然导致堆栈上的前一个ViewController出现。我如何使用swift来实现这一点?
当前回答
这就是我的解
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
}
其他回答
只需control +拖动栏项到func下面。魅力工作
@IBAction func done(sender: AnyObject) {
if((self.presentingViewController) != nil){
self.dismiss(animated: false, completion: nil)
print("done")
}
}
在离开电流控制器之前,我需要显示警报。所以我是这样做的:
添加扩展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)
}
我的偏好是在导航控制器中覆盖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,因为它会导致自定义设置的问题。
在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。
将按钮替换为另一个答案中建议的自定义按钮可能不是一个好主意,因为您将失去默认的行为和样式。
另一个选择是在视图控制器上实现viewWillDisappear方法,并检查名为isMovingFromParentViewController的属性。如果那个属性为真,它意味着视图控制器正在消失,因为它正在被移除(弹出)。
应该是这样的:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isMovingFromParentViewController {
// Your code...
}
}
在swift 4.2中
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isMovingFromParent {
// Your code...
}
}