我需要执行一个动作(清空一个数组),当UINavigationController的后退按钮被按下,而按钮仍然导致堆栈上的前一个ViewController出现。我如何使用swift来实现这一点?
当前回答
这里有一个最简单的Swift 5解决方案,它不需要你创建一个自定义的后退按钮,也不需要你放弃所有免费获得的UINavigationController左键功能。
正如Brandon A上面建议的那样,你需要在你想要与之交互的视图控制器中实现UINavigationControllerDelegate。一个好方法是创建一个unwind segue,你可以手动或自动地执行,并从自定义完成按钮或后退按钮重用相同的代码。
首先,让你感兴趣的视图控制器(你想检测返回的那个)在它的viewDidLoad中成为导航控制器的委托:
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.delegate = self
}
其次,在文件底部添加一个扩展,覆盖navigationController(willShow:animated:)
extension PickerTableViewController: UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController,
willShow viewController: UIViewController,
animated: Bool) {
if let _ = viewController as? EditComicBookViewController {
let selectedItemRow = itemList.firstIndex(of: selectedItemName)
selectedItemIndex = IndexPath(row: selectedItemRow!, section: 0)
if let selectedCell = tableView.cellForRow(at: selectedItemIndex) {
performSegue(withIdentifier: "PickedItem", sender: selectedCell)
}
}
}
}
因为你的问题包含了一个UITableViewController,所以我包含了一种获取用户点击行的索引路径的方法。
其他回答
我的偏好是在导航控制器中覆盖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.")
}
}
对于Swift 5,我们可以检查它在视图中是否会消失
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isMovingFromParent {
delegate?.passValue(clickedImage: selectedImage)
}
}
在离开电流控制器之前,我需要显示警报。所以我是这样做的:
添加扩展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)
}
推荐文章
- swift语言中的结构与类
- 我如何在Swift连接字符串?
- 请求失败:不可接受的内容类型:文本/html使用AFNetworking 2.0
- 缺少推荐的图标文件-该包不包含iPhone / iPod Touch的应用程序图标,像素为“120x120”,png格式
- 以编程方式创建segue
- Xcode 10的对象库去哪了?
- Xcode 10的UI元素在哪里?
- 我应该如何从字符串中删除所有的前导空格?- - - - - -斯威夫特
- Xcode构建失败“架构x86_64未定义的符号”
- 如何使用Xcode创建。ipa文件?
- 我可以在没有“构建和运行”的情况下启动iPhone模拟器吗?
- 动态改变UILabel的字体大小
- Xcode 4 -在新的Macintosh安装上的配置文件上“没有找到有效的签名标识”错误
- Xcode +删除所有断点
- 在iPhone上确定用户是否启用了推送通知