If I want to handle changes to a UITextField, such as the user typing in it; it seems like this can be done either by assigning a delegate to that text field, and then having the delegate implement shouldChangeCharactersInRange, or by adding a target to the textField, and handling the UIControlEventEditingChanged event.
Aside from the fact that with the delegate method, you can return NO and therefor stop the user from making the edit, is there any difference between these 2 things?
Same question for handling the beginning of editing or the ending of editing. It could be done either with the appropriate delegate methods or with the appropriate events. What is the textField delegate actually for if the control events can do the necessary work?
shouldChangeCharactersInRange is called before a change occurs, and gives you opportunity to 'cancel' the change. UIControlEventEditingChanged is called after the change occurred.
You can determine the resulting value of the textField in shouldChangeCharactersInRange, but you have to manually apply the replacementString to the existing text, using the supplied range. (via NSString stringByReplacingCharactersInRange). If you want to know the resulting text, it's easier and more efficient to use UIControlEventEditingChanged.
shouldChangeCharactersInRange is often used to implement validation checking of input - that is, you can filter characters/pasted text as it is entered. If a field is for phone numbers, for example, you can return FALSE if the user types a non numeric character, or attempts to paste in text that isn't numeric.
You might find a case where you can reuse code for multiple controls if you can stick with the UIControlEvent-methods.
You're right; you can essentially do the same thing via both, but UIControl is lower level and lets you siphon off each particular UIEvent to different targets via [UIControl addTarget:action:forControlEvents:] where as there is only a single delegate.
I would also say that the UITextField delegate protocol is simply there as a more convenient, higher level alternative to UIControl/UIEvent as a way to manage the behaviour of a UITextField.
The most common delegate pattern is UITableView DataSource and Delegate and I would say that using the UITextField delegate protocol is quite similar and therefore looks far more straight forward with more defined intentions than handing the messages from UIControl directly.
One key difference I've found between the two approaches posed in the original question is that the delegate "shouldChangeCharactersInRange" gets called BEFORE the value in the UITextField changes. The target for UIControlEventEditingChanged gets called AFTER the value in the UITextField changes.
In the case that you're using these events to make sure (for example) that all fields in a dialog are completely filled in before enabling a "Done" button, the target approach may work better for you. It did for me.
The delegation approach is the way to homogenize UITextField and UITextView behavior.
UITextView does not have control events. In contrast, UITextFieldDelegate and UITextviewDelegate provide parallel methods.
I have found out that shouldChangeCharactersInRange passes the same NSRange for insertion and deletion of text. You append a space and then delete it, and the parameters from shouldChangeCharactersInRange are indistinguishable from duplication of the text.
So shouldChangeCharactersInRange actually cannot predict the resulting text.
Related
I want to use a UITextField so that only part of it will be editable.
I know about the delegation and shouldChangeCharactersInRange but for some reason, copying the ranged part is allowed.
My goal is to get similar result to this (the 'subject' text part) without being able to copy it.
Should i use a different UITextField with textFieldDidBeginEditing returning false all the time?
Is there a better solution?
In the screenshot, a UILabel placed next to the UITextField is used. I'd recommend doing this as it will give you more options when you decide to style the text.
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.
With UIAccessibilityFocus protocol, supposedly, if you override accessibilityElementDidBecomeFocused() and accessibilityElementDidLoseFocus(), you will be able to track when an accessible element gain or lose focus while Voiceover is running. This seems to work well with all field types - UIButton, UILabel, UISwitch, UITextView, etc. - except UITextField. When Voiceover focus is on (or leaving) an UITextField, those functions are simply not called. Just wondering if it is a bug or something else. Thanks!
This is a feature, let me explain.
Without VoiceOver turned on there is no concept of focus within iOS. Except in the case of UITextField. UITextFields get "focused" (again focus isn't really a concept in iOS without voiceover) with or without VoiceOver on. For the other elements, this is not the case. They do not have "gainFocus" equivalents. A UIButton gaining focus is only meaningful from an accessibility standpoint. So they add in the special accessibilityElementDidGainFocus calls for those classes. They are specifically removed from UITextFields because that call would be logically equivalent to calls that already exist for that class, independent of the Accessibility API.
I wanted to ask a quick question just to make sure I am not missing anything simple before I implement a more difficult method. I need to create a custom keyboard for an iPhone application. This I have already done by creating a view with the buttons, using a custom input view and it displays exactly like it should. Now most of the buttons are standard numbers which need to update a UITextField in the screen that called the keyboard. Does anyone know a simple way to do this? I assume there has to be a built in function that the keyboard uses to send the information but I haven't been able to find any reference to it. Otherwise I will have to go the more difficult route. If anyone has a simple way to do this I would appreciate it. I haven't worked with custom keyboards before.
You won't be able to do it the same way that Apple does it, as their keyboard is basically an input device, globally.
I recommend you just append the data in your button press multiplex method. Here's an example:
NSString *appendThisText = #"subtitle";
self.myTextView.text=[NSString stringWithFormat:#"%#%#", self.myTextView.text, appendThisText];
Custom keyboards are simpler than you realise.
UITextField conforms to the UITextInput protocol. That's a bit of a red-herring because this protocol provides all the really complex stuff like selecting text and so on. But UITextInput itself conforms to UIKeyInput. This is your friend.
The key UIKeyInput methods are:
- (void)insertText:(NSString *)text;
- (void)deleteBackward;
Your keyboard class should have a delegate (which points to the textfield that the keyboard is operating on) and you simply call these methods to insert and delete text.
dose anyone know how to detect a delete press from a numberpad in ios?
If you're using a UITextField, your delegate's textField:shouldChangeCharactersInRange:replacementString: will be called with a range of length 1 and an empty replacement string. If nothing is deleted, however, you will get no notification.
If you're using a UITextView, your delegate's textView:shouldChangeTextInRange:replacementText: will be called with a range of length 1 and an empty replacement string. If nothing is deleted, however, you will get no notification.
If you're using your own class that implements UIKeyInput, deleteBackward is supposed to be called. I don't know whether a class implementing UITextInput (which itself includes UIKeyInput) might ever have replaceRange:withText: or setMarkedText:selectedRange: called instead with a range of length 1 and an empty replacement string, or what might happen in those cases if there is nothing to delete.
If you are implementing something like a passcode, I think a hidden textfield would be preferable, and more controls.