UITextField 文本更改事件

发布于 2024-11-29 08:58:21 字数 742 浏览 1 评论 0原文

如何检测文本字段中的任何文本更改?委托方法 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;
}

How can I detect any text changes in a textField? The delegate method shouldChangeCharactersInRange works for something, but it did not fulfill my need exactly. Since until it returns YES, the textField texts are not available to other observer methods.

e.g. in my code calculateAndUpdateTextFields did not get the updated text, the user has typed.

Is their any way to get something like textChanged Java event handler.

- (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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(22

萝莉病 2024-12-06 08:58:21

来自 执行 uitextfield 文本更改回调的正确方法

我捕获发送到 UITextField 控件的字符,如下所示:

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

In Objective-C:

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

In Swift:

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

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

您可以使用它并将 calculateAndUpdateTextFields 作为您的选择器

From proper way to do uitextfield text change call back:

I catch the characters sent to a UITextField control something like this:

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

In Objective-C:

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

In Swift:

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

Then in the textFieldDidChange method you can examine the contents of the textField, and reload your table view as needed.

You could use that and put calculateAndUpdateTextFields as your selector.

同展鸳鸯锦 2024-12-06 08:58:21

XenElement 的答案是正确的。

上述操作也可以在界面生成器中完成,方法是右键单击 UITextField 并将“编辑更改”发送事件拖动到您的子类单元。

UITextField 更改事件

XenElement's answer is spot on.

The above can be done in interface builder too by right-clicking on the UITextField and dragging the "Editing Changed" send event to your subclass unit.

UITextField Change Event

壹場煙雨 2024-12-06 08:58:21

设置事件监听器:

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

实际监听:

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

to set the event listener:

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

to actually listen:

- (void)textFieldDidChange:(UITextField *)textField {
    NSLog(@"text changed: %@", textField.text);
}
浮云落日 2024-12-06 08:58:21

Swift:

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

然后,实现回调函数:

@objc final private func yourHandler(textField: UITextField) {
    print("Text changed")
}

Swift:

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

Then, implement the callback function:

@objc final private func yourHandler(textField: UITextField) {
    print("Text changed")
}
涙—继续流 2024-12-06 08:58:21

如此处所述:UITextField 文本更改事件,似乎从 iOS 开始6(已检查 iOS 6.0 和 6.1)仅通过观察来完全检测 UITextField 对象的变化是不可能的UITextFieldTextDidChangeNotification

现在似乎只跟踪由内置 iOS 键盘直接进行的更改。这意味着,如果您仅通过调用以下内容来更改 UITextField 对象:myUITextField.text = @"any_text",您根本不会收到有关任何更改的通知。

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

我对此的“解决方案”是亲自为我对 UITextField 所做的每项更改发布通知(如果该更改是在不使用内置 iOS 键盘的情况下完成的)。像这样的事情:

myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";

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

[NSNotificationCenter.defaultCenter 
  postNotification:myTextFieldUpdateNotification];

这样,您就可以 100% 确信,当您更改 UITextField 对象的 .text 属性时,无论是更新它,您都会收到相同的通知在代码中“手动”或通过内置 iOS 键盘。

重要的是要考虑到,由于这不是记录的行为,因此这种方法可能会导致您的 UITextField 对象中收到相同更改的 2 个通知。根据您的需求(UITextField.text 更改时您实际执行的操作),这可能会给您带来不便。

如果您确实需要知道该通知是您自己的还是“iOS 制作的”,则稍微不同的方法是发布自定义通知(即使用 UITextFieldTextDidChangeNotification 之外的自定义名称)。

编辑:

我刚刚找到了一种我认为可能更好的不同方法:

这涉及到的键值观察(KVO)功能Objective-C (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA)。

基本上,您将自己注册为属性的观察者,如果该属性发生更改,您会收到通知。 “原理”与 NSNotificationCenter 的工作方式非常相似,这是该方法从 iOS 6 开始自动工作的主要优点(无需任何特殊调整,例如必须手动发布通知)。

对于我们的 UITextField 场景,如果您将此代码添加到包含文本字段的 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”属性不会随每次更新而更新。输入/删除新字母。相反,在您放弃文本字段的第一响应者状态后,文本字段对象会“整体”更新。

As stated here: UITextField text change event, it seems that as of iOS 6 (iOS 6.0 and 6.1 checked) it is not possible to fully detect changes in UITextField objects just by observing the UITextFieldTextDidChangeNotification.

It seems that only those changes made directly by the built-in iOS keyboard are tracked now. This means that if you change your UITextField object just by invoking something like this: myUITextField.text = @"any_text", you won't be notified about any changes at all.

I don't know if this is a bug or it is intended. Seems like a bug since I haven't found any reasonable explanation in documentation. This is also stated here: UITextField text change event.

My "solution" to this is to actually post a notification by myself for every change I make to my UITextField (if that change is done without using the built-in iOS keyboard). Something like this:

myUITextField.text = @"I'm_updating_my_UITextField_directly_in_code";

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

[NSNotificationCenter.defaultCenter 
  postNotification:myTextFieldUpdateNotification];

This way you are 100% confident that you'll receive the same notification when you change the .text property of your UITextField object, either when you update it "manually" in your code or through the built-in iOS keyboard.

It is important to consider that, since this is not a documented behavior, this approach may lead to 2 notifications received for the same change in your UITextField object. Depending on your needs (what you actually do when your UITextField.text changes) this could be an inconvenience for you.

A slightly different approach would be to post a custom notification (this is, with a custom name other than UITextFieldTextDidChangeNotification) if you actually need to know whether the notification was yours or "iOS-made".

EDIT:

I've just found a different approach which I think could be better:

This involves the Key-Value Observing (KVO) feature of Objective-C (http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueObserving/KeyValueObserving.html#//apple_ref/doc/uid/10000177-BCICJDHA).

Basically, you register yourself as an observer of a property and if this property changes you get notified about it. The "principle" is quite similar to how NSNotificationCenter works, being the main advantage that this approach works automatically also as of iOS 6 (without any special tweak like having to manually post notifications).

For our UITextField-scenario this works just fine if you add this code to, for example, your UIViewController that contains the text field:

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];

}

Credit to this answer regarding "context" management: https://stackoverflow.com/a/12097161/2078512

Note: Seems like while you are in the process of editing a UITextField with the built-in iOS keyboard, the "text" property of the text field is not updated with every new letter typed/removed. Instead, the text field object gets updated "as a whole" after you resign the first responder status of the text field.

魔法少女 2024-12-06 08:58:21

我们可以轻松地从 Storyboard 进行配置,按住 CTRL 拖动 @IBAction 并更改事件,如下所示:

在此处输入图像描述

We can easily configure that from Storyboard, CTRL drag the @IBAction and change event as following:

enter image description here

神也荒唐 2024-12-06 08:58:21

从 iOS 14 开始,无需创建选择器,您可以传递带有闭包的 UIAction

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

Starting iOS 14 there is no need to make a selector, you can pass a UIAction with a closure instead:

let editingChanged = UIAction { _ in
    // Do something when text changes...
}
myTextField.addAction(editingChanged, for: .editingChanged)
三生路 2024-12-06 08:58:21

这里有相同的快速版本。

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

func textFieldDidChange(textField: UITextField) {

}

谢谢

Here in swift version for same.

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

func textFieldDidChange(textField: UITextField) {

}

Thanks

伪心 2024-12-06 08:58:21

我解决了更改 shouldChangeChractersInRange 行为的问题。如果您返回“否”,则 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
}

I resolved the issue changing the behavior of shouldChangeChractersInRange. If you return NO the changes won't be applied by iOS internally, instead you have the opportunity to change it manually and perform any actions after the changes.

- (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
}
或十年 2024-12-06 08:58:21

已测试的 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!)

}

Swift Version tested:

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

Parameters explained:

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

Then add the method you created above in your UIViewController:

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

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

}
痴者 2024-12-06 08:58:21

斯威夫特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 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!)

}
初见 2024-12-06 08:58:21

对于 Swift 3.0:

let textField = UITextField()

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

使用如下类:

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

    }
}

For Swift 3.0:

let textField = UITextField()

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

using class like:

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

    }
}
烟燃烟灭 2024-12-06 08:58:21
  1. KVO 解决方案不起作用

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)

但是,请小心:

  • 您可能只想调用它一次,因此不要调用它,例如< code>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)
        }

    }

}

提示 - 不要不要忘记 super 调用必须在 post 调用之前进行!)

没有可用的解决方案,除非您通过以下方式修复控件子类化如上所示。这是唯一解决方案。

请注意,通知

UITextView.textDidChangeNotification

会导致

func textViewDidChangeSelection(_ textView: UITextView) 

被调用。

不是 textViewDidChange 。)

  1. KVO solutions do not work

KVO does NOT work in iOS for controls: http://stackoverflow.com/a/6352525/1402846 https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/KVO.html

  1. In the observing class, you do this:

Given that you know the text view you want to watch:

var watchedTextView: UITextView!

Do this:

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

However, be careful with that:

  • it's likely you only want to call that once, so do not call it in, for example, layoutSubviews

  • it's quite difficult to know when to best call it during your bring-up process. It will depend on your situation. Unfortunately there is no standard, locked-in solution

  • for example you usually certainly can not call it at init time, since of course watchedTextView may not exist yet

.

  1. the next problem is that ...

None of the notifications are called when text is changed programmatically.

This is a huge, age-old, and stupid, nuisance in iOS engineering.

Controls simply do not - end of story - call the notifcations when the .text property is changed programmatically.

This is insanely annoying because of course - obviously - every app ever made sets the text programmatically, such as clearing the field after the user posts, etc.

You have to subclass the text view (or similar control) like this:

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)
        }

    }

}

(Tip - don't forget the super call has to come before ! the post call.)

There is no solution available, unless, you fix the control by subclassing as shown just above. That is the only solution.

Note that the notification

UITextView.textDidChangeNotification

results in

func textViewDidChangeSelection(_ textView: UITextView) 

being called.

(Not textViewDidChange .)

谜兔 2024-12-06 08:58:21

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 3 Version

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

And get the changes in here

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

Hope it helps.

国产ˉ祖宗 2024-12-06 08:58:21

斯威夫特 3.1:

选择器:类名.方法名

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

  func fieldChanged(textfieldChange: UITextField){

    }

Swift 3.1:

Selector: ClassName.MethodName

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

  func fieldChanged(textfieldChange: UITextField){

    }
怪我入戏太深 2024-12-06 08:58:21

你应该使用通知来解决这个问题,因为另一种方法会监听输入框而不是实际的输入,特别是当你使用中文输入法时。
在viewDidload中

[[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;
} 

}

最后,你运行,就完成了。

You should use the notification to solve this problem,because the other method will listen to the input box not the actually input,especially when you use the Chinese input method.
In viewDidload

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFiledEditChanged:)
                                                 name:@"UITextFieldTextDidChangeNotification"
                                               object:youTarget];

then

- (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;
} 

}

finally,you run,will done.

翻了热茶 2024-12-06 08:58:21

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

   }

}

不要忘记设置委托。

Swift 3 Version:

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

   }

}

Don't forget to set the delegate.

鱼忆七猫命九 2024-12-06 08:58:21

带闭合:

   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
 }

With closure:

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

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

and using

textField.targetAction? = {
 // will fire on text changed
 }
南汐寒笙箫 2024-12-06 08:58:21
[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(didChangeTextViewText:) 
name:UITextFieldTextDidChangeNotification object:nil];



- (void) didChangeTextViewText {
 //do something
}
[[NSNotificationCenter defaultCenter] addObserver:self 
selector:@selector(didChangeTextViewText:) 
name:UITextFieldTextDidChangeNotification object:nil];



- (void) didChangeTextViewText {
 //do something
}
站稳脚跟 2024-12-06 08:58:21

一件事是您可能有多个 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)
}

One thing is you may have multiple UITextFields. So, give them a tag and then you can switch on the tags. Here's how to setup an observer in any class pretty much.

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)
}
攒一口袋星星 2024-12-06 08:58:21

SwiftUI

如果您使用本机 SwiftUI TextField 或仅使用 UIKit UITextField (这里是如何),您可以观察文本更改,例如:

SwiftUI 3.0

就像 SwiftUI 2(如下)一样,只需 2 (oldValue/newValue) 参数。

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) { change in
                print(change) // You can do anything due to the change here.
                // self.autocomplete(change) // like this
            }
    }
}

SwiftUI 1.0

对于较旧的 iOS 和其他 SwiftUI 1.0 平台,您可以在 combine 框架的帮助下使用 onReceive

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

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

SwiftUI

If you are using the native SwiftUI TextField or just using the UIKit UITextField (here is how), you can observe for text changes like:

SwiftUI 3.0

Like the SwiftUI 2 (below) just with 2 (oldValue/newValue) parameter.

SwiftUI 2.0

From iOS 14, macOS 11, or any other OS contains SwiftUI 2.0, there is a new modifier called .onChange that detects any change of the given state:

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

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

SwiftUI 1.0

For older iOS and other SwiftUI 1.0 platforms, you can use onReceive with the help of the combine framework:

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

Note that you can use text.publisher instead of Just(text) but it returns the change instead of the entire value.

夜访吸血鬼 2024-12-06 08:58:21

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)
}

Swift 4 Version

Using Key-Value Observing
Notify objects about changes to the properties of other objects.

var textFieldObserver: NSKeyValueObservation?

textFieldObserver = yourTextField.observe(\.text, options: [.new, .old]) { [weak self] (object, changeValue) in
  guard let strongSelf = self else { return }
  print(changeValue)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文