在后退按钮点击完成编辑 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的主要内容,如果未能解决你的问题,请参考以下文章