如何检查 UITextField 何时更改?
How do I check when a UITextField changes?
我正在尝试检查文本字段何时更改,这也等同于用于 textView 的函数 - textViewDidChange
到目前为止我已经这样做了:
func textFieldDidBeginEditing(textField: UITextField) {
if self.status.text == "" && self.username.text == "" {
self.topRightButton.enabled = false
} else {
self.topRightButton.enabled = true
}
}
哪种有效,但是 topRightButton
在按下文本字段后立即启用,我希望它仅在实际输入文本时启用?
SWIFT
Swift 4.2
textfield.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)
和
@objc func textFieldDidChange(_ textField: UITextField) {
}
SWIFT 3 & swift 4.1
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)
和
func textFieldDidChange(_ textField: UITextField) {
}
SWIFT 2.2
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged)
和
func textFieldDidChange(textField: UITextField) {
//your code
}
OBJECTIVE-C
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
而 textFieldDidChange 方法是
-(void)textFieldDidChange :(UITextField *) textField{
//your code
}
您可以使用 UITextFieldDelegate 中的委托方法。每次字符更改都会触发。
(Objective C) textField:shouldChangeCharactersInRange:replacementString:
(Swift) textField(_:shouldChangeCharactersInRange:replacementString:)
然而,这只会在 进行更改之前触发(实际上,只有当您从此处 return 为真时,才会进行更改)。
到目前为止我的处理方式:在UITextFieldDelegate
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
// text hasn't changed yet, you have to compute the text AFTER the edit yourself
let updatedString = (textField.text as NSString?)?.stringByReplacingCharactersInRange(range, withString: string)
// do whatever you need with this updated string (your code)
// always return true so that changes propagate
return true
}
Swift4 版本
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
return true
}
您可以在界面生成器中进行此连接。
在故事板中,单击屏幕顶部的助理编辑器(中间的两个圆圈)。
Ctrl + 单击界面生成器中的文本字段。
从 EditingChanged 拖动到助手视图中的视图控制器内部 class。
为您的函数命名(例如 "textDidChange")并单击“连接”。
Swift 3
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(sender:)), for: UIControlEvents.editingChanged)
这是您可以使用 Swift 3:
添加 textField text change listener
的方法
将您的 class 声明为 UITextFieldDelegate
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
textField.addTarget(self, action: #selector(UITextFieldDelegate.textFieldShouldEndEditing(_:)), for: UIControlEvents.editingChanged)
}
然后按照传统方式添加一个 textFieldShouldEndEditing 函数:
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { // do stuff
return true
}
textField(_:shouldChangeCharactersIn:replacementString:) 在 Xcode 8 为我工作,Swift 3 如果你想检查每一个按键。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Whatever code you want to run here.
// Keep in mind that the textfield hasn't yet been updated,
// so use 'string' instead of 'textField.text' if you want to
// access the string the textfield will have after a user presses a key
var statusText = self.status.text
var usernameText = self.username.text
switch textField{
case self.status:
statusText = string
case self.username:
usernameText = string
default:
break
}
if statusText == "" && usernameText == "" {
self.topRightButton.enabled = false
} else {
self.topRightButton.enabled = true
}
//Return false if you don't want the textfield to be updated
return true
}
Swift 5.0
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
for: .editingChanged)
及处理方式:
@objc func textFieldDidChange(_ textField: UITextField) {
}
Swift 4.0
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
for: UIControlEvents.editingChanged)
及处理方式:
@objc func textFieldDidChange(_ textField: UITextField) {
}
Swift 3.0
textField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
及处理方式:
func textFieldDidChange(textField: UITextField) {
}
Swift 3.0.1+(其他一些 swift 3.0 答案不是最新的)
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
for: UIControlEvents.editingChanged)
func textFieldDidChange(_ textField: UITextField) {
}
也许使用 RxSwift?
需要
pod 'RxSwift', '~> 3.0'
pod 'RxCocoa', '~> 3.0'
显然添加导入
import RxSwift
import RxCocoa
所以你有 textfield : UITextField
let observable: Observable<String?> = textField.rx.text.asObservable()
observable.subscribe(
onNext: {(string: String?) in
print(string!)
})
你还有其他3种方法..
- onError
- 已完成
- onDisposed
- onNext
swift 4
在 viewDidLoad() 中:
//ADD BUTTON TO DISMISS KEYBOARD
// Init a keyboard toolbar
let toolbar = UIView(frame: CGRect(x: 0, y: view.frame.size.height+44, width: view.frame.size.width, height: 44))
toolbar.backgroundColor = UIColor.clear
// Add done button
let doneButt = UIButton(frame: CGRect(x: toolbar.frame.size.width - 60, y: 0, width: 44, height: 44))
doneButt.setTitle("Done", for: .normal)
doneButt.setTitleColor(MAIN_COLOR, for: .normal)
doneButt.titleLabel?.font = UIFont(name: "Titillium-Semibold", size: 13)
doneButt.addTarget(self, action: #selector(dismissKeyboard), for: .touchUpInside)
toolbar.addSubview(doneButt)
USDTextField.inputAccessoryView = toolbar
添加此功能:
@objc func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
Swift 4
符合UITextFieldDelegate。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// figure out what the new string will be after the pending edit
let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
// Do whatever you want here
// Return true so that the change happens
return true
}
Swift 4
textField.addTarget(self, action: #selector(textIsChanging), for: UIControlEvents.editingChanged)
@objc func textIsChanging(_ textField:UITextField) {
print ("TextField is changing")
}
如果你想在用户完全输入后进行更改(一旦用户关闭键盘或按回车键就会调用)。
textField.addTarget(self, action: #selector(textDidChange), for: UIControlEvents.editingDidEnd)
@objc func textDidChange(_ textField:UITextField) {
print ("TextField did changed")
}
txf_Subject.addTarget(self, action:#selector(didChangeFirstText), for: .editingChanged)
@objc func didChangeText(textField:UITextField) {
let str = textField.text
if(str?.contains(" "))!{
let newstr = str?.replacingOccurrences(of: " ", with: "")
textField.text = newstr
}
}
@objc func didChangeFirstText(textField:UITextField) {
if(textField.text == " "){
textField.text = ""
}
}
您应该按照以下步骤操作:
- 引用文本字段的 Outlet
- 将 UITextFieldDelegate 分配给控制器 class
- 配置yourTextField.delegate
- 实现您需要的任何功能
示例代码:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var yourTextFiled : UITextField!
override func viewDidLoad() {
super.viewDidLoad()
yourTextFiled.delegate = self
}
func textFieldDidEndEditing(_ textField: UITextField) {
// your code
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// your code
}
.
.
.
}
Swift 4.2
在viewDidLoad中写这个
// to detect if TextField changed
TextField.addTarget(self, action: #selector(textFieldDidChange(_:)),
for: UIControl.Event.editingChanged)
在 viewDidLoad 之外写这个
@objc func textFieldDidChange(_ textField: UITextField) {
// do something
}
您可以通过 UIControl.Event.editingDidBegin 或任何您想检测的方式更改事件。
以防万一您对 SwiftUI 解决方案感兴趣,这个对我有用:
TextField("write your answer here...",
text: Binding(
get: {
return self.query
},
set: { (newValue) in
self.fetch(query: newValue) // any action you need
return self.query = newValue
}
)
)
我不得不说这不是我的主意,我是在这个博客上读到的:SwiftUI binding: A very simple trick
如果无法将 addTarget 绑定到您的 UITextField,我建议您按照上面的建议绑定其中一个,并在 shouldChangeCharactersIn 方法的末尾插入执行代码。
nameTextField.addTarget(self, action: #selector(RegistrationViewController.textFieldDidChange(_:)), for: .editingChanged)
@objc func textFieldDidChange(_ textField: UITextField) {
if phoneNumberTextField.text!.count == 17 && nameTextField.text!.count > 0 {
continueButtonOutlet.backgroundColor = UIColor(.green)
} else {
continueButtonOutlet.backgroundColor = .systemGray
}
}
并且在调用 shouldChangeCharactersIn func.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else {
return true
}
let lastText = (text as NSString).replacingCharacters(in: range, with: string) as String
if phoneNumberTextField == textField {
textField.text = lastText.format("+7(NNN)-NNN-NN-NN", oldString: text)
textFieldDidChange(phoneNumberTextField)
return false
}
return true
}
iOS13+
现在有一个 UITextField 委托方法可用
optional func textFieldDidChangeSelection(_ textField: UITextField)
我正在尝试检查文本字段何时更改,这也等同于用于 textView 的函数 - textViewDidChange
到目前为止我已经这样做了:
func textFieldDidBeginEditing(textField: UITextField) {
if self.status.text == "" && self.username.text == "" {
self.topRightButton.enabled = false
} else {
self.topRightButton.enabled = true
}
}
哪种有效,但是 topRightButton
在按下文本字段后立即启用,我希望它仅在实际输入文本时启用?
SWIFT
Swift 4.2
textfield.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)
和
@objc func textFieldDidChange(_ textField: UITextField) {
}
SWIFT 3 & swift 4.1
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), for: .editingChanged)
和
func textFieldDidChange(_ textField: UITextField) {
}
SWIFT 2.2
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingChanged)
和
func textFieldDidChange(textField: UITextField) {
//your code
}
OBJECTIVE-C
[textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
而 textFieldDidChange 方法是
-(void)textFieldDidChange :(UITextField *) textField{
//your code
}
您可以使用 UITextFieldDelegate 中的委托方法。每次字符更改都会触发。
(Objective C) textField:shouldChangeCharactersInRange:replacementString:
(Swift) textField(_:shouldChangeCharactersInRange:replacementString:)
然而,这只会在 进行更改之前触发(实际上,只有当您从此处 return 为真时,才会进行更改)。
到目前为止我的处理方式:在UITextFieldDelegate
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
// text hasn't changed yet, you have to compute the text AFTER the edit yourself
let updatedString = (textField.text as NSString?)?.stringByReplacingCharactersInRange(range, withString: string)
// do whatever you need with this updated string (your code)
// always return true so that changes propagate
return true
}
Swift4 版本
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
return true
}
您可以在界面生成器中进行此连接。
在故事板中,单击屏幕顶部的助理编辑器(中间的两个圆圈)。
Ctrl + 单击界面生成器中的文本字段。
从 EditingChanged 拖动到助手视图中的视图控制器内部 class。
为您的函数命名(例如 "textDidChange")并单击“连接”。
Swift 3
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(sender:)), for: UIControlEvents.editingChanged)
这是您可以使用 Swift 3:
添加textField text change listener
的方法
将您的 class 声明为 UITextFieldDelegate
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self
textField.addTarget(self, action: #selector(UITextFieldDelegate.textFieldShouldEndEditing(_:)), for: UIControlEvents.editingChanged)
}
然后按照传统方式添加一个 textFieldShouldEndEditing 函数:
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { // do stuff
return true
}
textField(_:shouldChangeCharactersIn:replacementString:) 在 Xcode 8 为我工作,Swift 3 如果你想检查每一个按键。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// Whatever code you want to run here.
// Keep in mind that the textfield hasn't yet been updated,
// so use 'string' instead of 'textField.text' if you want to
// access the string the textfield will have after a user presses a key
var statusText = self.status.text
var usernameText = self.username.text
switch textField{
case self.status:
statusText = string
case self.username:
usernameText = string
default:
break
}
if statusText == "" && usernameText == "" {
self.topRightButton.enabled = false
} else {
self.topRightButton.enabled = true
}
//Return false if you don't want the textfield to be updated
return true
}
Swift 5.0
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
for: .editingChanged)
及处理方式:
@objc func textFieldDidChange(_ textField: UITextField) {
}
Swift 4.0
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
for: UIControlEvents.editingChanged)
及处理方式:
@objc func textFieldDidChange(_ textField: UITextField) {
}
Swift 3.0
textField.addTarget(self, action: #selector(textFieldDidChange(textField:)), for: .editingChanged)
及处理方式:
func textFieldDidChange(textField: UITextField) {
}
Swift 3.0.1+(其他一些 swift 3.0 答案不是最新的)
textField.addTarget(self, action: #selector(ViewController.textFieldDidChange(_:)),
for: UIControlEvents.editingChanged)
func textFieldDidChange(_ textField: UITextField) {
}
也许使用 RxSwift?
需要
pod 'RxSwift', '~> 3.0'
pod 'RxCocoa', '~> 3.0'
显然添加导入
import RxSwift
import RxCocoa
所以你有 textfield : UITextField
let observable: Observable<String?> = textField.rx.text.asObservable()
observable.subscribe(
onNext: {(string: String?) in
print(string!)
})
你还有其他3种方法..
- onError
- 已完成
- onDisposed
- onNext
swift 4
在 viewDidLoad() 中:
//ADD BUTTON TO DISMISS KEYBOARD
// Init a keyboard toolbar
let toolbar = UIView(frame: CGRect(x: 0, y: view.frame.size.height+44, width: view.frame.size.width, height: 44))
toolbar.backgroundColor = UIColor.clear
// Add done button
let doneButt = UIButton(frame: CGRect(x: toolbar.frame.size.width - 60, y: 0, width: 44, height: 44))
doneButt.setTitle("Done", for: .normal)
doneButt.setTitleColor(MAIN_COLOR, for: .normal)
doneButt.titleLabel?.font = UIFont(name: "Titillium-Semibold", size: 13)
doneButt.addTarget(self, action: #selector(dismissKeyboard), for: .touchUpInside)
toolbar.addSubview(doneButt)
USDTextField.inputAccessoryView = toolbar
添加此功能:
@objc func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
Swift 4
符合UITextFieldDelegate。
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// figure out what the new string will be after the pending edit
let updatedString = (textField.text as NSString?)?.replacingCharacters(in: range, with: string)
// Do whatever you want here
// Return true so that the change happens
return true
}
Swift 4
textField.addTarget(self, action: #selector(textIsChanging), for: UIControlEvents.editingChanged)
@objc func textIsChanging(_ textField:UITextField) {
print ("TextField is changing")
}
如果你想在用户完全输入后进行更改(一旦用户关闭键盘或按回车键就会调用)。
textField.addTarget(self, action: #selector(textDidChange), for: UIControlEvents.editingDidEnd)
@objc func textDidChange(_ textField:UITextField) {
print ("TextField did changed")
}
txf_Subject.addTarget(self, action:#selector(didChangeFirstText), for: .editingChanged)
@objc func didChangeText(textField:UITextField) {
let str = textField.text
if(str?.contains(" "))!{
let newstr = str?.replacingOccurrences(of: " ", with: "")
textField.text = newstr
}
}
@objc func didChangeFirstText(textField:UITextField) {
if(textField.text == " "){
textField.text = ""
}
}
您应该按照以下步骤操作:
- 引用文本字段的 Outlet
- 将 UITextFieldDelegate 分配给控制器 class
- 配置yourTextField.delegate
- 实现您需要的任何功能
示例代码:
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var yourTextFiled : UITextField!
override func viewDidLoad() {
super.viewDidLoad()
yourTextFiled.delegate = self
}
func textFieldDidEndEditing(_ textField: UITextField) {
// your code
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// your code
}
.
.
.
}
Swift 4.2
在viewDidLoad中写这个
// to detect if TextField changed
TextField.addTarget(self, action: #selector(textFieldDidChange(_:)),
for: UIControl.Event.editingChanged)
在 viewDidLoad 之外写这个
@objc func textFieldDidChange(_ textField: UITextField) {
// do something
}
您可以通过 UIControl.Event.editingDidBegin 或任何您想检测的方式更改事件。
以防万一您对 SwiftUI 解决方案感兴趣,这个对我有用:
TextField("write your answer here...",
text: Binding(
get: {
return self.query
},
set: { (newValue) in
self.fetch(query: newValue) // any action you need
return self.query = newValue
}
)
)
我不得不说这不是我的主意,我是在这个博客上读到的:SwiftUI binding: A very simple trick
如果无法将 addTarget 绑定到您的 UITextField,我建议您按照上面的建议绑定其中一个,并在 shouldChangeCharactersIn 方法的末尾插入执行代码。
nameTextField.addTarget(self, action: #selector(RegistrationViewController.textFieldDidChange(_:)), for: .editingChanged)
@objc func textFieldDidChange(_ textField: UITextField) {
if phoneNumberTextField.text!.count == 17 && nameTextField.text!.count > 0 {
continueButtonOutlet.backgroundColor = UIColor(.green)
} else {
continueButtonOutlet.backgroundColor = .systemGray
}
}
并且在调用 shouldChangeCharactersIn func.
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
guard let text = textField.text else {
return true
}
let lastText = (text as NSString).replacingCharacters(in: range, with: string) as String
if phoneNumberTextField == textField {
textField.text = lastText.format("+7(NNN)-NNN-NN-NN", oldString: text)
textFieldDidChange(phoneNumberTextField)
return false
}
return true
}
iOS13+
现在有一个 UITextField 委托方法可用optional func textFieldDidChangeSelection(_ textField: UITextField)