在后退按钮点击完成编辑 UITextField

Posted

技术标签:

【中文标题】在后退按钮点击完成编辑 UITextField【英文标题】:Finish editing UITextField on back button tap 【发布时间】:2017-12-08 16:22:00 【问题描述】:

我在 NavigationController 中有 2 个控制器。首先将第二个推送到堆栈,用户可以与那里的文本字段进行交互。然后(在一种情况下)用户将点击后退按钮以转到上一个屏幕。假设第二个的加载是“重”的,所以一旦需要,我将只保留它的一个实例。

预期: 一旦按下后退按钮,我想隐藏键盘。

实际: 当我第二次回到第二个时,第一响应者一直在恢复。如何防止这种情况?辞职第一响应者也没有解决问题......

问题演示: https://gitlab.com/matrejek/TestApp

主要代码部分:

class FirstViewController: UIViewController 
    var child: UIViewController = 
        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let vc = storyboard.instantiateViewController(withIdentifier: "child")
        return vc
    ()

    override func viewDidLoad() 
        super.viewDidLoad()
    

    @IBAction func onButtonTap(_ sender: Any) 
        self.navigationController?.pushViewController(child, animated: true)
    


class SecondViewController: UIViewController 
    @IBOutlet weak var textField: UITextField!

    override func viewDidLoad() 
        super.viewDidLoad()
    

    override func viewWillDisappear(_ animated: Bool) 
        super.viewWillDisappear(animated)
        view.endEditing(true)
    

【问题讨论】:

交换viewWillDisappear()中的行?不需要在覆盖中调用super - 如果需要,您可以在执行“消失”任务后调用它。 【参考方案1】:

这看起来确实很奇怪 --- 而且您的方法似乎应该有效。

显然(基于快速测试),由于您不允许导航控制器释放 SecondVC,因此文本字段保持“活动状态”。

如果您将此添加到SecondViewController,它将阻止键盘在您下次导航到控制器时“自动重新显示” - 不确定它是否适合您,但它会完成这项工作:

override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)
    DispatchQueue.main.async 
        self.view.endEditing(true)
    


编辑:2020 年 1 月 25 日

基于新的 cmets,是的,这似乎是一个错误。

我之前的变通答案奏效了——有点。结果是键盘弹出,然后在随后按下child 时消失。

以下是更好的解决方法。我们让 SecondViewController 符合 UITextFieldDelegate 并添加一个 BOOL 类 var / 属性,以防止文本字段成为第一响应者。注释应该清楚:

class FirstViewController: UIViewController 
    var child: UIViewController = 
        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let vc = storyboard.instantiateViewController(withIdentifier: "child")
        return vc
    ()

    @IBAction func onButtonTap(_ sender: Any) 
        self.navigationController?.pushViewController(child, animated: true)
    


// conform to UITextFieldDelegate
class SecondViewController: UIViewController, UITextFieldDelegate 
    @IBOutlet weak var textField: UITextField!

    // bool var to prevent text field re-becoming first responder
    // when VC is pushed a second time
    var bResist: Bool = false

    override func viewDidLoad() 
        super.viewDidLoad()

        // assign text field delegate
        textField.delegate = self
    

    override func viewDidAppear(_ animated: Bool) 
        super.viewDidAppear(animated)
        // view has appeared, so allow text field to become first responder
        bResist = false
    

    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool 
        return !bResist
    

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

        // end editing on this view
        view.endEditing(true)

        // we want to resist becoming first responder on next push
        bResist = true
    

【讨论】:

我最近也在为这个问题苦苦挣扎。我自己的调查表明问题可能并不那么简单:您可以在对DispatchQueue.main.asyncAfter 的调用中将调用设置为endEditing,并为延迟设置一些任意值,然后键盘将被关闭。它看起来有问题,可能是一个杂物,但与提供的解决方案相比,它看起来同样有问题。我怀疑这实际上是一个视图生命周期时间问题。事实上,正如 DonMag 所说,不保留对其他 VC 的引用将解决问题。 另外,如果您打印导航堆栈中视图控制器的数量,您确实可以确认第二个 VC 不再存在,您甚至可以使用CFGetRetainCount(_:) 来查看保留计数增加推后,然后在弹出后递减。我认为这个问题可能需要苹果的关注。 我向 Apple 提交了错误报告。 @MH175 - 是的,Xcode 11 / ios 13 仍然存在问题,所以我也将其称为错误。我已经用更好的解决方法编辑了我的答案,以防止“故障”键盘显示/隐藏问题,

以上是关于在后退按钮点击完成编辑 UITextField的主要内容,如果未能解决你的问题,请参考以下文章

如何在不单击后退按钮的情况下隐藏键盘[重复]

如何在ActionMode中禁用操作栏后退按钮

按下后退按钮时强制重新加载/刷新

后退按钮“和”编辑按钮

xcode swift - 无法编辑后退按钮

在(后退按钮、前进按钮、关闭选项卡/浏览器)上运行最后一个 Ajax 请求 [重复]