I have UITextField that I have formatting code attached on textFieldDidEndEditing:. This works fine, but when I first load the text field with a text value (someTextField.text = #"...") the formatting doesn't happen. Of course, I can add another formatter there, but it seems kind of repetitive.
Is there a way to make all changes to a UITextField, programmatic or user originated, have formatting applied automatically?
Just run the same method from both places...
- (void)setTextFieldWithText:(NSString *)text {
//do formatting here...
self.textField.text = formattedText;
}
You can either add UITextFieldDidChangeNotification or just add a observer(using the addObserver method) to observe changes to the textfield. Choose which suits your approach. Both of them does cut the repetitive code. KVO - concept related to your question.
you might get some idea if you take a look at the following links
UITextFieldDidChangeNotification - How do i notify changes in UITextField?
addObserver method - detecting the change of content of UITextField when the change is not made by the keyboard
Note: Although the classes of the UIKit framework generally do not support KVO, you can still implement it in the custom objects of your application, including custom views.
Related
I am working with keyboard resign features in iPhone app development. I would like to know why
self.textField.delegate = self
needs to be included into the viewDidLoad of a viewController. I have tried to find reasons of this but no explanation has been clear so far.
A few points
The reason you need to set the delegate is because without it the view doesn't know about the view controller. So it wouldn't know about your method textFieldDidEndEditing and it would never be called.
That is the basic premise of delegate, you are telling that object, "here is an object that I want you to call methods on"
It doesn't have to be set in viewDidLoad - but it's often the most convient place to set up delegates for views.
The delegate doesn't have to be the view controller (self), in your case it's the simplest way, but with a UITableView its common to have another class be the delegate so that all the logic isn't in one place and so it can be changed.
The UITextFieldDelegate protocol defines methods that you use to manage the editing and validation of text in a UITextField object. All of the methods of this protocol are optional.
A text field calls the methods of its delegate in response to important changes. You use these methods to validate text that was typed by the user, to respond to specific interactions with the keyboard, and to control the overall editing process. Editing begins shortly before the text field becomes the first responder and displays the keyboard (or its assigned input view).
From more info. check apple doc.
Its not necessary to use self.textField.delegate = self if you don't want to manage the editing and validation of text in a UITextField object as all the methods of UITextFieldDelegate is optional.
For your other questions like what does .delegate = self do??
When you "set the delegate," what you are doing is saying where you want the messages to go.
Hence,
blah.delegate = amazingPlace will send the messages to "amazingPlace".
blah.delegate = somewhereElse will send the messages to "somewhereElse".
blah.delegate = self will send the messages to you.
... check this source link for details
Delegates are key concepts in iOS development so I'd suggest taking a good look at the documentation for them. It can be particularly useful to create your own custom delegates in certain situations too so understanding and using them in the right places can really help improve the structure of your projects.
There are a couple of key reasons for using them. Firstly, they allow safe communication between classes. In your example, the textField object that you're using is communicating back to your view controller. This is why you need to set your view controller as its delegate. Otherwise the text field doesn't have a delegate object (your view controller) to communicate with. The text field fires certain methods at certain times, such as textFieldDidBeginEditing, and calls these on its delegate object if it has one. When you register your view controller as the text view's delegate you can tap into these callbacks.
The other benefit is that delegates allow you to separate concerns and encapsulate or abstract responsibilities. It might be that the main concern for the text view is how to handle text in its view but not necessarily what to do when has been entered, or when the return button in the keyboard is pressed, or how to validate text that has been input. It's better that these tasks are handed over to something else, such as a delegate (in Obj-C parlance), and that is why in your example you have to register one class as the delegate for another.
As stated before, UITextfield delegation allows you to control events on your textfield.
You ll have the ability to edit functions like
textFieldShoulEndEditing
or
textFieldDidEndEditing
in order to add custom rules, for example : text validation.
Take a look at Apple doc.
If you don't need it, you can delete this line and UITextfieldDelegate on your class declaration.
You need to either set the delegate of a UITextField in code with self.textField.delegate = self
or make your viewcontroller (or any other class) a delegate with class MyViewController: UITextFieldDelegate and set the delegate of the UITextField in the storyboard by control dragging from the textfield to the viewController.
I am starting to work with text fields, and I want to implement a functionality with a custom autocomplete.
In a lot of blogs and answer, implement it with UITables to show the autocomplete, but I do not need this, I need to create a autocomplete like a iPhone function, where show a pop out with the filter but only with my array of words.
For example.
my_array = #{"apple","banana","pear","orange","berry"}
When I type "app" the text field only need to show me "apple" but not complete the text in the text field, should show the pop up with the autocomplete.
Something like this but only with my array.
You can build this behaviour yourself using the UITextFieldDelegate methods
( implement the delegate in your UIView
#interface someViewController : UIViewController <UITextFieldDelegate>
In doing this you get access to whatever the user has typed in
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
Where you can compare it to the items in your array and display another UIView or a custom button that when selected populates your text field.
Don't forget to tell your textfield who it's delegate should be, probably in your viewDidLoad method, but can also be done in the xib view
myTextField.delegate = self;
I know this seems laborious but it will be extremely gratifying.
Here's the apple doc for the UITextViewDelegate
I've implemented a custom auto complete textfield few days ago and the raywenderlich tutorial was helpful.
http://www.raywenderlich.com/336/auto-complete-tutorial-for-ios-how-to-auto-complete-with-custom-values
You probably need to implement your own table view to make it look like the screen you attached. The short tutorial will give you an idea how it should be done. I will post my code tomorrow if you want.
My colleagues and I prefer different approaches to solving one small task. We would like to know opinion of the community.
We have to process UITextField's text during editing. ( Text should be displayed in the view's title )
Two simplest approaches are:
1.Register for notifications:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(textFieldDidChangeNotification:)
name:UITextFieldTextDidChangeNotification
object:_titleTextField];
2.Use UITextFieldDelegate method
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSMutableString *mutableString = [textField.text mutableCopy];
[mutableString replaceCharactersInRange:range withString:string];
// use mutableString for father processing
return YES;
}
Which approach is better and why? Is there any reason why some approach should be avoided in this situation?
UPDATE: ( Some clarifications )
We do not need any additional flexibility that is provided by delegate ( like possibility to disallow some editing) or notifications ( possibility to add several observers ). Our main question is "Is it a good practice to use NSNotifications if we can easily solve an issue with delegate?"
UPDATE2:
Thanks everyone who answered the question!
It seems that community's answer for question "is it a good practice to use NSNotifications if we can easily solve an issue with delegate?" is yes. But for our original issue we have found another (third) variant which is better than delegates and NSNotification (see accepted answer).
I have coded a lot of both and I disagree with Adam. Notifications prove much harder to debug and trace backward most of the time. I also suspect they add more performance overhead, but that's anecdotal for me and I have not benchmarked it.
I lean toward notifications when there may be more than one observer that needs to act on an event, and/or when I want "loose coupling" where one part of the code shouldn't have specific knowledge of API's in another part.
In your case, the text field already comes with the logic to have a delegate and make calls to the delegate on certain events so it's a no-brainer. If one or more delegate methods get called at the time you need with the data you need. that's the simpler, more appropriate path.
The main difference between delegate and notification is that notification will notify all classes, in case they have subscribed to it. While delegate is one to one.
Considering that there won't be any further changes in application work flow. This approaches a pretty much equal. But I still prefer to use delegate because of following reasons:
it's more common approach, so it will make your code more readable and maintainable;
using notification you are have to subscribe to it, so it's extra lines. Not so many but ViewControllers usually are the largest classes in ios applications.
notifications use event DID while delegate use SHOLUD, so if you need to prevent your textfield from entering smth SHOULD fits better
Methods of a UITextFieldDelegate will return YES or NO depending on whether you want the user to be allowed to type certain things.
With this in mind, I'd use a notification. You don't care about the logic for changing the content of the UITextField, all you want to do is, whenever the content is changed, change the title of your view.
This gives you the benefit of allowing any delegate to still be able to return YES or NO if the content needs to be restricted and the notification will only be sent if the delegate has returned YES (or if there is no delegate).
EDIT
In case I misunderstood the question, process the text in the UITextFieldDelegate method and use the notification to update the view's title. Unless the UITextFieldDelegate is the view, in which case I'd just update the view's title directly from the UITextFieldDelegate method.
EDIT #2
Based on your further edit and requirements I would hands down use the delegate method. NSNotification comes with issues that delegates don't - debugging and performance (as RobP mentioned) is one. Another is it's much easier to leave an NSNotification hanging around after you have dealloc'd whatever it was attached to, resulting in a crash (good look debugging, see RobP's answer).
In your specific circumstances, delegate wins.
Since UITextField inherits from UIControl we also can use addTarget: action: forControlEvents:
[_textField addTarget:self action:#selector(textDidChange) forControlEvents:UIControlEventEditingChanged];
I've got a view controller xib file with several views in it. I'm building a wizard-type interface. I'm just doing a simple fade between the views, and I'm already using a navigation controller for the main interface. I'd prefer not to use one for this wizard. Anyway, in the views, each panel has at least a button, some sort of input field (usually a UITextField) and some helper text hard coded in a UILabel.
The problem is that not all the UITextField objects are calling the textFieldDidChange method in the delegate (File's Owner - .m file associated with the xib), but all the UITextField objects ARE calling the textFieldDidBeginEditing method.
Makes no sense to me. I feel like I must be missing something simple in how I set up the screens, but I'll be darned if I can figure it out. Each of the screens all look identical in the property sheets (on the right hand side of Xcode), and everything is wired up correctly in the File's Owner property sheet, both in IBOutlet and IBActions.
Here are some shots of what's going on...
Ideas? Thanks.
Here are links to the screen caps of the vital parts.
(being a new member is making it hard to add all the info I need with screen caps!)
As far as I now, there is no delegate method with the header textFieldDidChange. You have created a method of your own, which is depending on a NSNotification. Make sure all the UITextFields are send the right notification.
There is no such method on a UITextFieldDelegate
You may have confused textViewDidChange, which is a delegate method for a UITextView, but itis passed the UITextView that generated the event, not an NSNotification.
Seems like you want textField:shouldChangeCharactersInRange:replacementString: instead.
This is resolved. I'm a knucklehead. :-)
I was attaching my own notifier/observer and hadn't done so for the last few UITextField objects. Sorry to bother y'all.
I do not want the user to be able to select the first few characters of my UITextView. I have tried subclassing it and noticed methods such as -setSelectedRange: and -setSelectedTextRange:. Both are called at different times but it seems like it's the latter that I need.
The -setSelectedTextRange: method takes a UITextRange object, which has a UITextPosition property called "start". This sounds like what I want but I cannot write to it, and there are no classes for this object.
Does anyone have any ideas on how I can do this? FWIW, I'm trying to replicate what Facebook have on their "Check-In" view on their iPhone app.
Thanks in advance!
I'm not personally familiar with the functionality of the Facebook app Check-In view, but based on your description, it sounds like you need something like this in your subclass:
- (BOOL)becomeFirstResponder
{
if ([super becomeFirstResponder]) {
// Select text in field.
[self setSelectedTextRange:[self textRangeFromPosition:[self positionFromPosition:self.beginningOfDocument offset:1] toPosition:self.endOfDocument]];
return YES;
}
return NO;
}
In particular, note the "offset:1" argument. You should be able to use this to set the start of your selected text range. Also, you'll want to make sure that the new text range you specify is valid for the number of characters that are in the text field.