Implement setText:(NSString*)text method in subclassed UITextField - iphone

I'm subclassing UITextField and need a way to run some code whenever the text in the field changes, how can I do this?
(Writing the logic inside this class would let me write cleaner code outside it... I mean that I can do what I'm asking you using the UITextFieldDelegate, but I can access it only from outside the class.)

I came across the same use case of needing a custom clear button. I tried subclassing UITextField hoping that I could override setText: but that turned out to be a dead end as it isn't called every time a characters is typed or deleted as I hoped. I came up with the following solution:
- (void)awakeFromNib {
[super awakeFromNib];
self.clearButtonMode = UITextFieldViewModeNever;
UIButton *clearButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
[clearButton setTitle:#"x" forState:UIControlStateNormal];
[clearButton addTarget:self action:#selector(clearText:) forControlEvents:UIControlEventTouchDown];
self.rightView = clearButton;
[self addTarget:self action:#selector(textChanged:) forControlEvents:UIControlEventEditingChanged];
}
- (void)textChanged:(UITextField *)sender {
self.rightViewMode = sender.text.length > 0 ? UITextFieldViewModeWhileEditing : UITextFieldViewModeNever;
}
- (void)clearText:(UIButton *)sender {
self.text = #"";
[self textChanged:self];
}
Using the UIControlEventEditingChanged we can react to changes in text brought about by the keyboard but not by setting the text in code. Since I also want to respond to text brought about by the clearText: method I have to call the textChanged: method manually following the clear. If the text is set in code elsewhere there would be a need to call textChanged to compensate.

In .h file of your viewcontroller just define this deledate
#interface yourviewcontroller <UITextFieldDelegate>
After that in .m file use bellow code..
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
.....Do Somthing Here....
}
this is delegate method when textfield text changed this method called everytime
.

How is the code cleaner outside of it by not using the UITextFieldDelegate method? You're kind of breaking the MVC design paradigm by trying to tell a view class (your UITextField) how to respond to changes, which is what a controller is meant to do. Could you give a little more insight into why you think it's cleaner to override setText as opposed to handling things in your delegate implementation?

Related

Programmatically instantiating a Delegate to a component

I have an app which has a controller which already handles UITextFieldDelegate for textfields, now I want to add a second controller + UITextField programmatically which is separately from the main controller but is called from it.
So I have a MainController which handles input (that is working), then next to that, I defined this:
#interface TestUIDelegate : UIViewController <UITextFieldDelegate>{
TestUIDelegate has a property textField.
TestUIDelegate has a method:
- (void)initGUI:(UIView *)myView;
which initialises a textField like thus:
- (void)initGUI:(UIView *)myView {
self.view = myView;
textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 200, 300, 40)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.font = [UIFont systemFontOfSize:15];
textField.placeholder = #"enter text";
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.keyboardType = UIKeyboardTypeDefault;
textField.returnKeyType = UIReturnKeyDone;
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.delegate = self;
[self.view addSubview:textField];
}
which also works; the field shows up and is editable, keyboard comes up and you can type stuff.
So far so good, but now I want to Done button to work so the keyboard is dismissed, so I added:
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
NSLog(#"Here?");
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
NSLog(#"Or here?");
}
To my TestUIDelegate (actually I added all delegate methods from TextUIFieldDelegate).
I instantiate the TestUIDelegate from the didFinishLaunchingWithOptions in the MainController like this:
TestUIDelegate *controller = [[TestUIDelegate alloc] init];
[controller initGUI:self.view];
TextField still shows up the delegate methods are never called, none of them. Now I imagine i'm doing something very weird and I have looked through all answers on SO and in Google slightly relating to this, but they all do it by implementing the delegates in the MainController which is exactly what I really do not want. And I need it programmatically; not (at all) with the gui builder.
Can anyone enlighten me please? I don't think i'm going to figure this out on my own.
You need to add textFieldShouldReturn to get the keyboard to dismiss:
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
TextFieldDidEndEditing will then be called as well, but you need to resignFirstResponder before that happens.
I found out what the problem was (but not why...); I was using
[controller initGUI:self.view];
changing that to:
[controller initGUI:self.window.rootViewController.view];
makes it work. I don't know why.
For people who are interesting to do this same thing (like I said; I couldn't find even one example on the web), here is the simplified project; https://dl.dropboxusercontent.com/u/6134596/TestDelegate.zip

UITextField return key on subview

I've got a UIViewController with an additional small UIView I created on top of it (subview). When I click a button this view hovers to the center of the screen. The issue is the i've got a UITextField in the additional UIView and i cannot seem to get the return key to work.
Although I set my IBAction to the event "Editing did end" of the text field, when i click the return key, the IBAction doesn't run.
What am I doing wrong?
you just set Your Delegate for example :- yourtextfile.delegate=self; and also dont forget to add delegate method in to .h file
#interface contacts_detailView : UIViewController<UITextFieldDelegate>
and then you delegate textFieldDidEndEditing
- (void)textFieldDidEndEditing:(UITextField *)textField
{
//your new view apear code here
[textField resignFirstResponder];
}
make sure UITextFieldDelegate at interface
Clicking on "Return" doesn't trigger an "Editing did end" event. Only when you'll call resignFirstResponder on the UITextField will you see the event triggered.
What you should do is set your UIViewController as the delegate of the UITextField and implement the method
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
First of all, delegate the TextField to the file's owner like this:
yourtextField.delegate = self in your viewDidLoad.
And then add this to the view controller
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
It should work.
There is no need to write more code for key board return. Please write this in your .m file , it will work for any number of text field , no need to write again again for different textfield.
use <UItextfieldDelegate> in your .h file. Then make wiring with fileowner in nib file.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self.view endEditing:YES];
return YES;
}

Having Trouble With UITextField and NSString

I have the following code for UITextField. The problem I'm having is that the text does not persist. For example, when I present a modal view, then dismiss it, the UITextField does not have the text anymore in it. I want the text to remain there until I dimiss that view with the text field.
I am displaying the UITextField like this:
UITextField *nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
nameTextField.delegate = self;
[nameTextField addTarget:self action:#selector(editingEnded) forControlEvents:UIControlEventEditingDidEnd];
[nameTextField setEnabled: YES];
self.myTextField = nameTextField;
[nameTextField release];
Then I have:
- (void)editingEnded
{
NSString *tempRoutineName = self.myTextField.text;
self.routineName = tempRoutineName;
[tempRoutineName release];
}
Instead of editingEnded, Implement the UITextFieldDelegate protocol. Go to the textFieldDidEndEditing method and reassign the value of text in it.
Like,
-(void) textFieldDidEndEditing:(UITextField *)textField{
if (textField.tag ==0){
self.myTextField = textField;
// myTextField is a property
}
Now in the in the viewDidLoad method or the viewWillAppear method, go ahead and assign this value back to the textField.
If necessary use [tableView reloadData] if this is used in a tableView or use [self reloadInputViews] (if necessary).
Then again, its all logical. Nothing too complex in code.
Use UITextFieldDelegate method that is textFieldDidEndEditing, which gets called when editing ends
In my opinion:
NSString *tempRoutineName = self.myTextField.text;
self.routineName = tempRoutineName;
[tempRoutineName release];
You haven't own tempRoutineName to release. Comment out the release and check.

how can I call a method as I click UITextField?

I want to ask that how can I call a method as I do click(touch for start writing) in iphone UITextField, as like we click UIButton and put method in "addTarget", is there any way for UITextFields ?
implement a UITextFieldDelegate and do whatever you want to do in - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField or - (void)textFieldDidBeginEditing:(UITextField *)textField
You should use the first method if you want to stop the textfield from behaving like a textfield. For example if you want to open the textfield editor in a modal view. You can return NO there if you don't want this behavior.
Edit: Here is the code to call myMethod:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[self myMethod];
return YES;
}
You can set textField's delegate and implement textFieldShouldBeginEditing: method in it - that method will get called when user taps the field and before it goes into editing.
See UITextFieldDelegate reference for more methods available.
[textField addTarget:self action:#selector(myMethod:) forControlEvents:UIControlEventEditingChanged];
-(void) myMethod:(id)sender
{
UITextField* textField = (UITextField *)sender;
}
i think this will help..!!
You can code as,
[YourTextField addTarget:self action:#selector(myMethod:) forControlEvents:UIControlEventEditingDidBegin];
-(void)myMethod
{
[YourTextField resignFirstResponder];
//Do whatever you want
}

Disabling Keyboard

How to Hide Keyboard by pressing Returnkey
There is a couple of things you need to remember. The number #1 part developers forget to set is the delegate of the textField.
If you are using the Interface Builder, you must remember that you need to set the delegate of the textField to the file Owner.
alt text http://www.thoughtblog.com/imgs/delegate.png
If you are not using Interface Builder then make sure you set the delegate of the textfield to self. I also include the returnType. For Example if the textField was called gameField:
gameField.delegate = self;
gameField.returnType = UIReturnKeyDone;
You must also implement the UITextFieldDelegate for your ViewController.
#interface YourViewController : UIViewController <UITextFieldDelegate>
Finally you need to use the textFieldShouldReturn method and call [textField resignFirstResponder]
-(BOOL) textFieldShouldReturn:(UITextField*) textField {
[textField resignFirstResponder];
return YES;
}
All your textFields will use this same method so you only need to have this setup once. As long as the delegate is set for the textField, the UITextFieldDelegate is implemented for the interface, you add the textFieldShouldReturn method and call the
resignFirstResponder your set.
The keyboard only shows up when something editable (usually a UITextField) has become the first responder. Therefore, to make the keyboard go away, you have to make the textField not be the firstResponder anymore. Fortunately, it's one line of code:
[myTextField resignFirstResponder];
You really need to include more information with your question, but I think this might be what you are looking for:
First, make your view controller implement the UITextFieldDelegate:
#interface MainViewController : UIViewController <UITextFieldDelegate> {
Then add this method to the controller:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
Read the UITextFieldDelegate documentation to see what else you can do.
Use these two methods:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
activeTextField = textField;
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
activeTextField = nil;
[txtPassword resignFirstResponder];
[txtUserName resignFirstResponder];
return YES;
}
Please make sure you have given delegates to each textfields. For that you should go to the view. Right click . set the delegate to view.