ios/xcode/objective c: Capture last keystroke in textfield - ios

I have a method to enable the save button that I want to fire when the user meets several conditions, for example, username is at least 4 characters. To test these conditions I need to check with every keystroke. What is best touch event (through storyboard) to capture this?
Have tried "Editing did end" however, that doesn't fire until you click out of textfield. I'd rather see button enabled as soon as textfield has acceptable entry. Also tried on touchup inside and value changed but neither seem to work.
What is best touch event so that as soon as user types fourth character, button is enabled?
Here is action method that textfield is wired to. Note it does not say anything about touch event which is present in storyboard.
- (IBAction)changedText:(id)sender {
[self updateSaveButton];
-(void) updateSaveButton
{
NSString *name = self.username.text;
NSLog(#"update save button called");
self.submitButton.enabled = (name.length > 3);
}

What I do is to assign the text field a delegate. In this case, the delegate would whatever is the instance whose class's code you have shown in your question.
The delegate is sent a bunch of delegate messages, documented in UITextFieldDelegate. In this case, the one I would use is textField:shouldChangeCharactersInRange:replacementString:, which fires every time the user does anything that proposed to change the text in the field.
Simply respond as you see fit, and return YES to allow the change to take place.
Alternatively, you can treat the text field as a control (UIControl) and use the text field's Editing Changed control event to set up a target-action pair. But in actual practice I always end up using the delegate method instead.

Related

Executing a method in a dart TextField on every key press

I have a TextField in my project, which will be used to act as an autocomplete text field. I need it to respond to key presses.
After researching on Flutter's documentation, https://flutter.io/docs/cookbook/forms/text-field-changes, I found two ways of allowing a TextField to execute a method every time the TextField's text changed, however it only executes that method when you hit and enter and leave the focus of the TextField
I have used both the controller method, and the onChanged method and neither work.
Is there a way of having a TextField respond to every key press, as you type in a word?
OnChanged should work fine. If you are trying to change something on the screen you will have to make a call to setState() and your functionality with in that call.

Distinguishing between EditingDidBegin because of user action vs programatic setting

When I set the text of a UITextField programmatically, the EditingChanged action is not sent to my view controller, the action is only sent when the user changes the text through the keyboard.
However, when I call becomeFirstResponder() on a text field, it does send the EditingDidBegin action. So I can't tell if editing began because the user tapped on the UITextField, or because I did it programmatically. Do you know how I can easily distinguish between the two?
I'm looking for a way to know when the user taps in a UITextField and only when the user taps on it, not when becomeFirstResponder is called on it. Do you know of one?
when I call becomeFirstResponder()
The secret is that when you call becomeFirstResponder(), you call it. Your code is running. You are in control. You can do whatever you want.
So if you need your EditingChanged handler to know that you called becomeFirstResponder(), you simply have to make a notation of this fact beforehand. For example, you could have a Bool property justCalledBecomeFirstResponder which you set to true just before calling becomeFirstResponder(). Now your EditingChanged handler has only to examine (and possibly reset to false) this Bool property before proceeding.

iOS Accessibility - is there a way to tell when VoiceOver has changed focus?

I'd like to call a method every time a different element is focused while VoiceOver is active. I was hoping there would be some UIAccessibilityNotification for this, but I can't seem to find any.
Ultimately, my goal is to add an additional condition prior to reading the accessibility label. For example, as opposed to saying (by default) "If UIButton becomes focused: read label", I'd like to be able to say "When UIButton becomes focused AND UIButton's background color is blue: read label".
So my question is: how do I either add an additional condition prior to reading the label, or receive a notification when a new element becomes focused?
You can't explicitly tell when the user moves the VoiceOver cursor (just like you can't tell where a sighted user is looking).
For the behavior you want, you have two options:
Set the button's accessibilityLabel to an appropriate value whenever the other conditions change.
Subclass UIButton and override its accessibilityLabel getter method:
- (NSString *) accessibilityLabel {
if (SOME_CONDITION) {
return #"Hooray!";
} else {
return #"Womp womp";
}
}
If you need to disable an item entirely, rather than returning nil or a blank string, you should set its accessibilityElementsHidden property to YES.
You can use the UIAccessibilityFocus protocol to detect changes in focus by accessibility clients (including VoiceOver). Note that UIAccessibilityFocus is an informal protocol that each accessibility element must implement independently.
That said, for your use case, Aaron is right to suggest returning a different accessibilityLabel under each condition.

iOS 8 Keyboard Extension Detecting first responder change

I'm writing a keyboard extension for iOS (hence overriding UIInputViewController) and I'm trying to figure out how to detect when the first responder changes. Is this even possible?
My motivation is that when the user selects a different text input field (while the keyboard is active) the style of the keyboard might need to change to suit the attributes of that input. This can happen when there are several text fields displayed on a UI and the user first selects one (causing the keyboard to be initialized) then the user selects another with different attributes (keyboard doesn't know it).
I've looked through the methods exposed by UIInputViewController and the delegates it implements but nothing I've seen really fits the bill. The closest thing I've found is selectionDidChange on UITextInputDelegate.
I found the best way to get this information is to override the UITextInputDelegate textDidChange method (UIInputViewController implements UITextInputDelegate). It turns out that textDidChange is called whenever the user switches the input text field (first responder), or when the text changes for some reason (luckily not when it is your keyboard that initiated the change).
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
That should tell you when it expects to become firstResponder. A couple things to keep in mind;
*This will only be called when a UITextFied is the thing becoming firstResponder. If some other object decides to, this won't be called. It'll probably call the method below.
-(BOOL)becomeFirstResponder
*Your class must conform to the UITextFieldDelegate and all of your UITextFields must set their delegates to self. Without that they won't call shouldBeginEditing on your class.

Action when the small cross button of UITextField is pressed

I can add a small cross button that is used to clear all the text in a single click in a UITextField with the following code.
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
I also implemented UITextFieldDelegate.
I want to activate/deactivate the right bar button of the UINavigationBar according to the changes in my UITextField. The rule is simple: if the text field has at least one character, just enable the button, else disable it.
I implemented the UITextField's delegate method textField:shouldChangeCharactersInRange: to constantly check the requirement and update the status of the button.
Now my problem is, when I click the small cross button on the text field, the method textField:shouldChangeCharactersInRange: is not called. So the required action is missing. How can I identify the hit event of the clear button?
Some pictures to show what I'm talking about.
Initial stage: here, the "Done" button is disabled because there are no letters in the text field
When typing a letter, the "Done" button is enabled
Now, if I click on the clear button, the "Done" button is still enabled. This is wrong.
Use the delegate method textViewShouldClear::
Asks the delegate if the text field’s current contents should be
removed.
- (BOOL)textFieldShouldClear:(UITextField *)textField
Parameters
textField
The text field containing the text.
Return Value
YES if the text field’s contents should be cleared; otherwise, NO.
Discussion
The text field calls this method in response to the user pressing the
built-in clear button. (This button is not shown by default but can be
enabled by changing the value in the clearButtonMode property of the
text field.) This method is also called when editing begins and the
clearsOnBeginEditing property of the text field is set to YES.
Implementation of this method by the delegate is optional. If it is
not present, the text is cleared as if this method had returned YES.
Availability
* Available in iOS 2.0 and later.
Declared In
UITextField.h
You can use textFieldShouldClear: delegate method to handle when user taps on clear button.

Resources