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;
}
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(22)
来自 执行 uitextfield 文本更改回调的正确方法:
In Objective-C:
In Swift:
您可以使用它并将 calculateAndUpdateTextFields 作为您的
选择器
。From proper way to do uitextfield text change call back:
In Objective-C:
In Swift:
You could use that and put calculateAndUpdateTextFields as your
selector
.XenElement 的答案是正确的。
上述操作也可以在界面生成器中完成,方法是右键单击 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.
设置事件监听器:
实际监听:
to set the event listener:
to actually listen:
Swift:
然后,实现回调函数:
Swift:
Then, implement the callback function:
如此处所述:UITextField 文本更改事件,似乎从 iOS 开始6(已检查 iOS 6.0 和 6.1)仅通过观察来完全检测
UITextField
对象的变化是不可能的UITextFieldTextDidChangeNotification
。现在似乎只跟踪由内置 iOS 键盘直接进行的更改。这意味着,如果您仅通过调用以下内容来更改
UITextField
对象:myUITextField.text = @"any_text"
,您根本不会收到有关任何更改的通知。我不知道这是一个错误还是有意为之。似乎是一个错误,因为我在文档中没有找到任何合理的解释。这里也有说明:UITextField 文本更改事件。
我对此的“解决方案”是亲自为我对
UITextField
所做的每项更改发布通知(如果该更改是在不使用内置 iOS 键盘的情况下完成的)。像这样的事情:这样,您就可以 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
中,则效果很好:归功于此有关“上下文”管理的答案: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 theUITextFieldTextDidChangeNotification
.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:This way you are 100% confident that you'll receive the same notification when you change the
.text
property of yourUITextField
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 yourUITextField.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, yourUIViewController
that contains the text field: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.我们可以轻松地从
Storyboard
进行配置,按住 CTRL 拖动@IBAction
并更改事件,如下所示:We can easily configure that from
Storyboard
, CTRL drag the@IBAction
and change event as following:从 iOS 14 开始,无需创建选择器,您可以传递带有闭包的
UIAction
:Starting iOS 14 there is no need to make a selector, you can pass a
UIAction
with a closure instead:这里有相同的快速版本。
谢谢
Here in swift version for same.
Thanks
我解决了更改 shouldChangeChractersInRange 行为的问题。如果您返回“否”,则 iOS 不会在内部应用更改,而是您有机会手动更改它并在更改后执行任何操作。
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.
已测试的 Swift 版本:
参数说明:
然后将您在上面创建的方法添加到
UIViewController
中:Swift Version tested:
Parameters explained:
Then add the method you created above in your
UIViewController
:斯威夫特4
Swift 4
对于 Swift 3.0:
使用如下类:
For Swift 3.0:
using class like:
KVO 不适用于 iOS 控件:http: //stackoverflow.com/a/6352525/1402846 https://developer.apple.com/library/ archive/documentation/General/Conceptual/DevPedia-CocoaCore/KVO.html
假设您知道想要的文本视图观看:
这样做:
但是,请小心:
您可能只想调用它一次,因此不要调用它,例如< code>layoutSubviews
这相当困难了解在启动过程中何时最好调用它。这将取决于您的情况。 不幸的是,没有标准的、锁定的解决方案
例如,您通常当然不能不在
init 时间,因为当然
watchedTextView
可能还不存在,
。
当以编程方式更改文本时,不会调用任何通知。
这是 iOS 工程中一个巨大的、古老的、愚蠢的麻烦。
控件根本不会 - 故事结束 - 当 .text 属性以编程方式更改时调用通知。
这非常烦人,因为当然 - 显然 - 每个应用程序都以编程方式设置文本,例如在用户发布后清除字段等。
您必须像这样子类化文本视图(或类似的控件):(
提示 - 不要不要忘记 super 调用必须在 post 调用之前进行!)
没有可用的解决方案,除非您通过以下方式修复控件子类化如上所示。这是唯一解决方案。
请注意,通知
会导致
被调用。
(不是
textViewDidChange
。)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
Given that you know the text view you want to watch:
Do this:
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 coursewatchedTextView
may not exist yet.
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:
(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
results in
being called.
(Not
textViewDidChange
.)Swift 3 版本
并在此处获取更改
希望它有所帮助。
Swift 3 Version
And get the changes in here
Hope it helps.
斯威夫特 3.1:
Swift 3.1:
你应该使用通知来解决这个问题,因为另一种方法会监听输入框而不是实际的输入,特别是当你使用中文输入法时。
在viewDidload中
然后
}
最后,你运行,就完成了。
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
then
}
finally,you run,will done.
Swift 3 版本:
不要忘记设置委托。
Swift 3 Version:
Don't forget to set the delegate.
带闭合:
并使用
With closure:
and using
一件事是您可能有多个 UITextField。因此,给它们一个标签,然后您就可以打开标签。以下是如何在任何类中设置观察者的方法。
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.
SwiftUI
如果您使用本机 SwiftUI
TextField
或仅使用 UIKitUITextField
(这里是如何),您可以观察文本更改,例如:SwiftUI 3.0
就像 SwiftUI 2(如下)一样,只需 2 (
oldValue/newValue
) 参数。SwiftUI 2.0
从 iOS 14、macOS 11 或任何其他包含 SwiftUI 2.0 的操作系统开始,有一个名为
.onChange
的新修饰符,可以检测给定state
的任何更改:SwiftUI 1.0
对于较旧的 iOS 和其他 SwiftUI 1.0 平台,您可以在 combine 框架的帮助下使用
onReceive
:请注意, 可以使用
text.publisher
而不是Just(text)
,但它返回更改而不是整个值。SwiftUI
If you are using the native SwiftUI
TextField
or just using the UIKitUITextField
(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 givenstate
:SwiftUI 1.0
For older iOS and other SwiftUI 1.0 platforms, you can use
onReceive
with the help of the combine framework:Note that you can use
text.publisher
instead ofJust(text)
but it returns the change instead of the entire value.Swift 4 版本
使用键值观察
通知对象有关其他对象属性的更改。
Swift 4 Version
Using Key-Value Observing
Notify objects about changes to the properties of other objects.