UITextField文本更改事件

我如何检测文本字段中的任何文本变化?委托方法shouldChangeCharactersInRange适用于某些东西,但它并不能完全满足我的需求。因为在它返回YES之前,textField文本对其他观察器方法是不可用的。

例如,在我的代码calculateAndUpdateTextFields没有得到更新的文本,用户已经输入。

是他们的任何方式获得类似textChanged Java事件处理程序。

- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
if (textField.tag == kTextFieldTagSubtotal
|| textField.tag == kTextFieldTagSubtotalDecimal
|| textField.tag == kTextFieldTagShipping
|| textField.tag == kTextFieldTagShippingDecimal)
{
[self calculateAndUpdateTextFields];


}


return YES;
}
405943 次浏览

从# EYZ0:

我捕获发送到UITextField控件的字符,就像这样:

// Add a "textFieldDidChange" notification method to the text field control.

在objective - c中:

[textField addTarget:self
action:@selector(textFieldDidChange:)
forControlEvents:UIControlEventEditingChanged];

迅速:

textField.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)

然后在textFieldDidChange方法中,您可以检查textField的内容,并根据需要重新加载表视图。

你可以使用它,把calculateAndUpdateTextFields作为你的selector

XenElement的答案是正确的。

以上也可以在接口构建器中通过右键单击UITextField并将“Editing Changed”发送事件拖放到你的子类单元中来完成。

UITextField Change Event

正如这里所述:UITextField文本更改事件,似乎从iOS 6开始 (iOS 6.0和6.1检查),仅通过观察UITextFieldTextDidChangeNotification,不可能完全检测到UITextField对象中的变化。

现在似乎只有那些由内置的iOS键盘直接做出的改变才会被追踪。这意味着,如果您只是通过调用myUITextField.text = @"any_text"这样的代码来更改UITextField对象,则根本不会收到任何更改通知。

我不知道这是一个错误还是故意的。似乎是一个bug,因为我在文档中没有找到任何合理的解释。这里也有说明:UITextField文本更改事件

我对此的“解决方案”是,我自己对UITextField所做的每一个更改都发布一个通知(如果没有使用内置的iOS键盘进行更改)。就像这样:

myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";


NSNotification *myTextFieldUpdateNotification  =
[NSNotification notificationWithName:UITextFieldTextDidChangeNotification
object:myUITextField];


[NSNotificationCenter.defaultCenter
postNotification:myTextFieldUpdateNotification];

这样,当你改变UITextField对象的.text属性时,你100%有信心收到相同的通知,无论是在代码中“手动”更新还是通过内置的iOS键盘更新。

考虑到这一点很重要,因为这不是一个记录在案的行为,这种方法可能会导致在UITextField对象中收到两个相同更改的通知。根据您的需要(当UITextField.text更改时您实际要做什么),这可能会给您带来不便。

一个稍微不同的方法是发布一个自定义通知(这是一个自定义名称,而不是UITextFieldTextDidChangeNotification),如果你真的需要知道这个通知是你的还是“ios制作的”。

编辑:

我刚刚发现了一个我认为更好的方法:

这涉及到Objective-C (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA)的Key-Value Observing (KVO)特性。

基本上,你把自己注册为一个属性的观察者,如果这个属性发生了变化,你会得到通知。“原理”与NSNotificationCenter的工作原理非常相似,这是这种方法在iOS 6中自动工作的主要优势(没有任何特殊的调整,如必须手动发布通知)。

对于我们的# eyz0场景来说,如果你将这段代码添加到包含文本字段的UIViewController中,这就很好了:

static void *myContext = &myContext;


- (void)viewDidLoad {
[super viewDidLoad];


//Observing changes to myUITextField.text:
[myUITextField addObserver:self forKeyPath:@"text"
options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld
context:myContext];


}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary *)change context:(void *)context {


if(context == myContext) {
//Here you get notified every time myUITextField's "text" property is updated
NSLog(@"New value: %@ - Old value: %@",
[change objectForKey:NSKeyValueChangeNewKey],
[change objectForKey:NSKeyValueChangeOldKey]);
}
else
[super observeValueForKeyPath:keyPath ofObject:object
change:change context:context];


}

关于“上下文”管理的答案:https://stackoverflow.com/a/12097161/2078512

注意:似乎当你用内置的iOS键盘在过程中编辑UITextField时,文本字段的“text”属性不会随着每一个新输入/删除的字母而更新。相反,在您重新指定文本字段的第一响应器状态后,文本字段对象将“作为一个整体”进行更新。

设置事件监听器。

[self.textField addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

真正倾听:

- (void)textFieldDidChange:(UITextField *)textField {
NSLog(@"text changed: %@", textField.text);
}

我解决了改变shouldChangeChractersInRange行为的问题。如果你返回NO,这些更改不会被iOS内部应用,相反,你有机会手动更改它,并在更改后执行任何操作。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
//Replace the string manually in the textbox
textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string];
//perform any logic here now that you are sure the textbox text has changed
[self didChangeTextInTextField:textField];
return NO; //this make iOS not to perform any action
}

这里是相同的swift版本。

textField.addTarget(self, action: "textFieldDidChange:", forControlEvents: UIControlEvents.EditingChanged)


func textFieldDidChange(textField: UITextField) {


}

谢谢

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didChangeTextViewText:)
name:UITextFieldTextDidChangeNotification object:nil];






- (void) didChangeTextViewText {
//do something
}

迅速:

yourTextfield.addTarget(self, action: #selector(yourHandler(textField:)), for: .editingChanged)

然后,实现回调函数:

@objc final private func yourHandler(textField: UITextField) {
print("Text changed")
}
你应该使用通知来解决这个问题,因为其他方法将侦听输入框而不是实际输入,特别是当你使用中文输入法时。 在viewDidload < / p >
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:)
name:@"UITextFieldTextDidChangeNotification"
object:youTarget];

然后

- (void)textFiledEditChanged:(NSNotification *)obj {
UITextField *textField = (UITextField *)obj.object;
NSString *toBestring = textField.text;
NSArray *currentar = [UITextInputMode activeInputModes];
UITextInputMode *currentMode = [currentar firstObject];
if ([currentMode.primaryLanguage isEqualToString:@"zh-Hans"]) {
UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
if (!position) {
if (toBestring.length > kMaxLength)
textField.text =  toBestring;
}

最后,你跑,就完了。

Swift测试版本:

//Somewhere in your UIViewController, like viewDidLoad(){ ... }
self.textField.addTarget(
self,
action: #selector(SearchViewController.textFieldDidChange(_:)),
forControlEvents: UIControlEvents.EditingChanged
)

参数解释道:

self.textField //-> A UITextField defined somewhere in your UIViewController
self //-> UIViewController
.textFieldDidChange(_:) //-> Can be named anyway you like, as long as it is defined in your UIViewController

然后在UIViewController中添加上面创建的方法:

//Gets called everytime the text changes in the textfield.
func textFieldDidChange(textField: UITextField){


print("Text changed: " + textField.text!)


}

我们可以很容易地从Storyboard配置,按CTRL拖动@IBAction并更改事件如下:

enter image description here

对于Swift 3.0:

let textField = UITextField()


textField.addTarget(
nil,
action: #selector(MyClass.textChanged(_:)),
for: UIControlEvents.editingChanged
)

像这样使用类:

class MyClass {
func textChanged(sender: Any!) {


}
}

斯威夫特3.1:

选择器:类名。MethodName

  cell.lblItem.addTarget(self, action: #selector(NewListScreen.fieldChanged(textfieldChange:)), for: .editingChanged)


func fieldChanged(textfieldChange: UITextField){


}

Swift 3版本:

class SomeClass: UIViewController, UITextFieldDelegate {


@IBOutlet weak var aTextField: UITextField!




override func viewDidLoad() {
super.viewDidLoad()


aTextField.delegate = self
aTextField.addTarget(self, action: #selector(SignUpVC.textFieldDidChange), for: UIControlEvents.editingChanged)
}


func textFieldDidChange(_ textField: UITextField) {


//TEXT FIELD CHANGED..SECRET STUFF


}


}

不要忘记设置委托。

关闭:

   class TextFieldWithClosure: UITextField {
var targetAction: (() -> Void)? {
didSet {
self.addTarget(self, action: #selector(self.targetSelector), for: .editingChanged)
}
}


func targetSelector() {
self.targetAction?()
}
}

和使用

textField.targetAction? = {
// will fire on text changed
}

斯威夫特4

func addNotificationObservers() {


NotificationCenter.default.addObserver(self, selector: #selector(textFieldDidChangeAction(_:)), name: .UITextFieldTextDidChange, object: nil)


}


@objc func textFieldDidChangeAction(_ notification: NSNotification) {


let textField = notification.object as! UITextField
print(textField.text!)


}

Swift 3版本

yourTextField.addTarget(self, action: #selector(YourControllerName.textChanges(_:)), for: UIControlEvents.editingChanged)

把零钱放在这里

func textChanges(_ textField: UITextField) {
let text = textField.text! // your desired text here
// Now do whatever you want.
}

希望能有所帮助。

Swift 4版本

使用键值观察

.

.

.

.
var textFieldObserver: NSKeyValueObservation?


textFieldObserver = yourTextField.observe(\.text, options: [.new, .old]) { [weak self] (object, changeValue) in
guard let strongSelf = self else { return }
print(changeValue)
}
  1. KVO解决方案do not work

KVO不工作在iOS控件:http://stackoverflow.com/a/6352525/1402846 https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/KVO.html

  1. 在观察课上,你要这样做:

假设你知道你想要观看的文本视图:

var watchedTextView: UITextView!

这样做:

NotificationCenter.default.addObserver(
self,
selector: #selector(changed),
name: UITextView.textDidChangeNotification,
object: watchedTextView)

但是,要注意:

  • 很可能你只想调用一次,所以不要调用它,例如,layoutSubviews

  • 在抚养孩子的过程中,很难知道什么时候最好。这取决于你的情况。不幸的是没有标准的,锁定的解决方案

  • 例如,你通常可以而不是init时间调用它,因为watchedTextView当然可能还不存在

  1. 下一个问题是……

当文本被更改时,将调用没有一个的通知。

这是iOS工程中一个巨大的、古老的、愚蠢的麻烦。

控件根本没有-故事结束 -当.text属性以编程方式更改时调用通知。

这是非常烦人的,因为每个应用程序都以编程方式设置文本,比如在用户发布后清除字段,等等。

你必须像这样子类化文本视图(或类似的控件):

class NonIdioticTextView: UIITextView {


override var text: String! {
// boilerplate code needed to make watchers work properly:
get {
return super.text
}
set {
super.text = newValue
NotificationCenter.default.post(
name: UITextView.textDidChangeNotification,
object: self)
}


}


}

(提示-不要忘记超级调用必须来之前 !邮政电话。)

< em >是< / em >解决方案可用,除非,你修复控件子类如上所示。这就是只< em > < / em >解决方案。

注意,通知

UITextView.textDidChangeNotification

结果

func textViewDidChangeSelection(_ textView: UITextView)

被称为。

(# eyz1 # eyz0。)

一个是你可能有多个uitextfield。所以,给他们一个标签,然后你可以打开标签。下面是如何在任何类中设置一个观察者。

private func setupTextFieldNotification() {
NotificationCenter.default.addObserver(forName: UITextField.textDidChangeNotification, object: nil, queue: OperationQueue.main) { (notification) in
if let textField = notification.object as? UITextField, textField.tag == 100, let text = textField.text {
print(#line, text)
}
}
}


deinit {
NotificationCenter.default.removeObserver(self)
}

SwiftUI

如果你使用的是原生SwiftUI TextField或者只是使用UIKit UITextField (这里是如何 .),你可以观察文本的变化,比如:

SwiftUI 2.0

从iOS 14, macOS 11,或任何其他包含SwiftUI 2.0的操作系统中,有一个名为.onChange的新修饰符,可以检测给定的state的任何变化:

struct ContentView: View {
@State var text: String = ""


var body: some View {
TextField("Enter text here", text: $text)
.onChange(of: text) {
print($0) // You can do anything due to the change here.
// self.autocomplete($0) // like this
}
}
}

SwiftUI 1.0

对于旧的iOS和其他SwiftUI 1.0平台,你可以在结合框架的帮助下使用onReceive:

import Combine
.onReceive(Just(text)) {
print($0)
}

注意,可以使用text.publisher而不是Just(text),但它返回的变化而不是整个值。

从iOS 14开始,你不需要创建选择器,你可以用一个闭包来传递UIAction:

let editingChanged = UIAction { _ in
// Do something when text changes...
}
myTextField.addAction(editingChanged, for: .editingChanged)