I am fairly new to iphone programming and here I am facing some issues. Now in my application, I have two textfields and I want to fire an event while second textfield starts editing. now I am using following function
- (void)textFieldDidBeginEditing:(UITextField *)textField
but the thing is the event is being fired when the first textfield starts editing. It does not wait for the second text field. Is there any way I can use this function for the second textfield or may be somehow could know and pass it the value of the active textfield?
I tried writing the name of the textfield instead of (UITextField *)textField in the function but still the same result.
If I were you , I would set a tag (in Interface Builder) of the second textField to 2, or something similar. Then you can just do this:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
if (textField.tag == 2) {
//this is textfield 2, so call your method here
}
}
EDIT: Please do this to see if the method is even called:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
NSLog(#"The method was called");
}
For Swift 2.2
func textFieldDidBeginEditing(textField: UITextField) {
if textField.tag == 2 {
//this is textfield 2, so call your method here
}
}
That delegate method is gonna get called everytime the editing of ANY text field is started, so it should be you who controls what is done when this happens. I suggest you to do something like:
-(void)textFieldDidBeginEditing: (UITextField *)textField
{
if (textField == mySecondTextField)
{
//Do what you need
}
else
{
//Do nothing
}
}
I hope it helps you!
Utilitize the tag property in Interface Builder to identify your view objects in your application at runtime. It will make life a lot easier, especially when you get ready to localize your application for different languages.
In your header file for your view controller
#define kUsernameField 100
#define kPasswordField 101
#define kStartButton 300
In the view controller implementation file
- (void)textFieldDidBeginEditing:(UITextField *)textField {
switch (textField.tag) {
case kUsernameField:
// do user name stuff
break;
case kPasswordField:
// do password stuff
break;
default:
NSLog(#"No case statement for %#", [textField description]);
break;
}
}
You will find a lot of tutorial out there that use the title field of UIButton to identify them. For example:
- (IBAction)buttonTouchUp:(id)sender {
UIButton *button = (UIButton *)sender;
// don't like
if ([button.currentTitle isEqualToString:#"Start"] == NSOrderedSame) {
// because if localize your for other language then you will have
// include code for those other language
// French: Démarrer
// Spanish: Inicio
// blah blah blah
}
// better
if (button.tag == kStartButton) {
// very simple, no code changes for localization
// blah blah blah
}
}
If you are creating the object with code, you can set the tag:
button.tag = kStartButton;
// or
[button setTag:kStartButton];
You must declare first UITextFieldDelegate in your controller .h
And set the delegate of your text field. ex. myInput.delegate = self;
-(void)textFieldDidBeginEditing:(UITextField *)sender
{
if ([sender isEqual:myInput])
{
NSLog(#"test");
}
}
This works perfectly for me.
Have you checked if your second textViews delegate is set to self ? I had the same issue where I had forgotten to set the delegate of other textFields and hence the delegate method was not firing.
Please have a look to my answer in this Question, it's exactly what you're looking for
Objective C: what is a "(id) sender"?
Related
I have this app and a reset button to reset the values that I entered. I'm trying to get the button to be gray as long as I don't enter a valid value.
When the value is valid, it should enable and become touchable...
How can I do this?
I am using this code but it isn't working...
//Reset values
- (IBAction)resetPressed:(UIButton *)sender {
if (didPan==1) {
resetPressed.enabled = YES;
} else {
resetPressed.enabled = NO;
}
self.prozent=0;
didPan=NO;
//remove drawn intersection line
[intersectionLine removeFromSuperview];
NSLog(#"resetPressed");
}
To enable the button if it matches your criteria, use setEnabled:YES.
E.g.
UIButton *button = (UIButton *)sender;
[button setEnabled:YES];
An even better way to do this would be to use the dot notated version, like such:
button.enabled = YES;
In your condition you are using if (didPan==1) { although it would be giving the required result but it is better to use if(didPan)
secondly resetPresed is action name not the button or sender, so you should use sender instead of resetPressed
and for setting button status use [sender setEnabled:YES];//OR sender.enabled=YES;
so your code would look like this
- (IBAction)resetPressed:(UIButton *)sender {
if (didPan) {
[sender setEnabled:YES]; //OR sender.enabled=YES;
} else {
[sender setEnabled:NO]; // OR sender.enabled=NO;
}
}
If you are entering a value in a UITextField, you could set the delegate for the text field and write code for enabling/disabling inside textFieldDidEndEditing: method of the delegate object.
i.e; theButton.enabled = YES/NO
From your code it looks like you are writing code for disabling the button inside the action of that button itself which won't work if the button is disabled.
***I did solve the problem after long time of searching.
I found out that the ResetButton must have a Property
it looks like this
#property (strong, nonatomic) IBOutlet UIButton *resetButton;
Then I highlighted the button and unchecked enabled from the control(tried it before but it didn't work)
The I used button.enabled=YES and changed the colour using [resetButton setAlpha:1] for normal and [resetButton setAlpha:0.5] for not activated
Thanks guys for your help!*
if you enter the value for example in a UITextField, then use the delegate of the textfield to determine if the value is correct:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([textField.text isValid]) { // check if text in textfield is valid
button.enabled = YES;
} else {
button.enabled = NO;
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)sender
{
if(sender.returnKeyType == UIReturnKeyNext){
// Make something else first responder
}else if(sender.returnKeyType == UIReturnKeyGo){
// Do something
}else{
[sender resignFirstResponder];
}
return YES;
}
I have a UITextFieldDelegate using this. I'm new to iPhone dev stuff. Coming from web, I'm used to defining events dynamically and minimally. Is this an "ok" way to go from Username to Password UITextFields?
Is there a better common practice?
This has been discussed extensively here: How to navigate through textfields (Next / Done Buttons)
But the quick answer is yes, this is fine! Nothing hacky about it.
If you have the text fields declared as properties of the class, you could simply compare sender to each text field to determine the correct course of action. I would probably do something like this.
- (BOOL)textFieldShouldReturn:(UITextField *)sender
{
if (sender == self.firstTextField)
[self.secondTextField becomeFirstResponder];
else if (sender == self.secondTextField)
[self doSomething];
else
[sender resignFirstResponder];
return YES;
}
I have a grouped table view that contains 3 sections and each row per section. The first two section rows contains UITextField(Name & Subject are the section titles) and the last one contains UITextView(Message is the section title) because i want to get some data from the user by this controller itself.
The two text fields have the returnKeyType as UIReturnKeyNext. For UITextView, the "return" button is present in keyboard to feed new line. So i used textFieldShouldReturn method to navigate to the next cell by pressing these return type buttons in UIKeyboard.
The next button will work fine with the first text field(Name). Here the problem comes... If i click the Next button of second cell, It goes to the UITextView(last cell) with one line down. That is, the cursor moves one line apart from its original position.
My code is...
-(BOOL) textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
if (textField == nameTextField) {
[subjectTextField becomeFirstResponder];
}
else if(textField == subjectTextField) {
[messageTextView becomeFirstResponder];
}
return YES;
}
What should i do to make this work fine? Thanks in Advance..
While testing a lot of stuff I found a simple yet suitable solution:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if ( [textField isEqual: nameTextField] )
{
[nameTextField resignFirstResponder];
[messageTextView becomeFirstResponder];
return NO;
}
return YES;
}
It handles the resigning of the nameTextField itself and returns NO to the request.
Basically what is happening is that when return is tapped you make text view the first responder and the return gets added to the text view. Thats why the cursor goes to the second line. Try doing this in your textViewDidChange: delegate method:
- (void)textViewDidChange:(UITextView *)textView {
if(textView.text == #"\r") {
textView.text = #"";
}
I am calling an action from textFieldDidBeginEditing as follows:
[dotButton addTarget:self action:#selector(actionButton:) forControlEvents:UIControlEventTouchUpInside];
and specifiying my action as:
- (void) actionButton:(id)sender {
textField.text = [textField.text stringByAppendingString:#"APPROVED"];
}
Simple question with hopefully a simple answer....
textField.text refers to the field named textField but how do I update the current field that textFieldDidBeginEditing is acting on at the time?? i.e can I set a variable to retrieve the current fieldname?
Thanks
You should check whether or not the textField the label of your interest.
An example:
if (textField == self.firstLabel){
//do something
}
else if (textField == self.secondLabel){
//do other something
}
The textField variable that is passed from the delegate method is the one that you should handle.
Tell me if it works. Good luck!
I've got a UISearchBar in my interface and I want to customise the behaviour of the the small clear button that appears in the search bar after some text has been entered (it's a small grey circle with a cross in it, appears on the right side of the search field).
Basically, I want it to not only clear the text of the search bar (which is the default implementation) but to also clear some other stuff from my interface, but calling one of my own methods.
I can't find anything in the docs for the UISearchBar class or the UISearchBarDelegate protocol - it doesn't look like you can directly get access to this behaviour.
The one thing I did note was that the docs explained that the delegate method:
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText;
is called after the clear button is tapped.
I initially wrote some code in that method that checked the search bar's text property, and if it was empty, then it had been cleared and to do all my other stuff.
Two problems which this though:
Firstly, for some reason I cannot fathom, even though I tell the search bar to resignFirstResponder at the end of my method, something, somewhere is setting it back to becomeFirstResponder. Really annoying...
Secondly, if the user doesn't use the clear button, and simply deletes the text in the bar using the delete button on the keyboard, this method is fired off and their search results go away. Not good.
Any advice or pointers in the right direction would be great!
Thanks!
Found the better solution for this problem :)
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText{
if ([searchText length] == 0) {
[self performSelector:#selector(hideKeyboardWithSearchBar:) withObject:searchBar afterDelay:0];
}
}
- (void)hideKeyboardWithSearchBar:(UISearchBar *)searchBar{
[searchBar resignFirstResponder];
}
The answer which was accepted is incorrect. This can be done, I just figured it out and posted it in another question:
UISearchbar clearButton forces the keyboard to appear
Best
I've got this code in my app. Difference is that I don't support 'live search', but instead start searching when the user touches the search button on the keyboard:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
if ([searchBar.text isEqualToString:#""]) {
//Clear stuff here
}
}
Swift version handling close keyboard on clear button click :
func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.characters.count == 0 {
performSelector("hideKeyboardWithSearchBar:", withObject:searchBar, afterDelay:0)
}
}
func hideKeyboardWithSearchBar(bar:UISearchBar) {
bar.resignFirstResponder()
}
You could try this:
- (void)viewDidLoad
{
[super viewDidLoad];
for (UIView *view in searchBar.subviews){
for (UITextField *tf in view.subviews) {
if ([tf isKindOfClass: [UITextField class]]) {
tf.delegate = self;
break;
}
}
}
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
// your code
return YES;
}
I would suggest using the rightView and rightViewMode methods of UITextField to create your own clear button that uses the same image. I'm assuming of course that UISearchBar will let you access the UITextField within it. I think it will.
Be aware of this from the iPhone OS Reference Library:
If an overlay view overlaps the clear button, however, the clear button always takes precedence in receiving events. By default, the right overlay view does overlap the clear button.
So you'll probably also need to disable the original clear button.
Since this comes up first, and far as I can see the question wasn't really adequately addressed, I thought I'd post my solution.
1) You need to get a reference to the textField inside the searchBar
2) You need to catch that textField's clear when it fires.
This is pretty simple. Here's one way.
a) Make sure you make your class a , since you will be using the delegate method of the textField inside the searchBar.
b) Also, connect your searchBar to an Outlet in your class. I just called mine searchBar.
c) from viewDidLoad you want to get ahold of the textField inside the searchBar. I did it like this.
UITextField *textField = [self.searchBar valueForKey:#"_searchField"];
if (textField) {
textField.delegate = self;
textField.tag = 1000;
}
Notice, I assigned a tag to that textField so that I can grab it again, and I made it a textField delegate. You could have created a property and assigned this textField to that property to grab it later, but I used a tag.
From here you just need to call the delegate method:
-(BOOL)textFieldShouldClear:(UITextField *)textField {
if (textField.tag == 1000) {
// do something
return YES;
}
return NO;
}
That's it. Since you are referring to a private valueForKey I can't guarantee that it will not get you into trouble.
Best solution from my experience is just to put a UIButton (with clear background and no text) above the system clear button and than connect an IBAction
- (IBAction)searchCancelButtonPressed:(id)sender {
[self.searchBar resignFirstResponder];
self.searchBar.text = #"";
// some of my stuff
self.model.fastSearchText = nil;
[self.model fetchData];
[self reloadTableViewAnimated:NO];
}
Wasn't able to find a solution here that didn't use a private API or wasn't upgrade proof incase Apple changes the view structure of the UISearchBar. Here is what I wrote that works:
- (void)viewDidLoad {
[super viewDidLoad];
UITextField* textfield = [self findTextFieldInside:self.searchBar];
[textfield setDelegate:self];
}
- (UITextField*)findTextFieldInside:(id)mainView {
for (id view in [mainView subviews]) {
if ([view isKindOfClass:[UITextField class]]) {
return view;
}
id subview = [self findTextFieldInside:view];
if (subview != nil) {
return subview;
}
}
return nil;
}
Then implement the UITextFieldDelegate protocol into your class and overwrite the textFieldShouldClear: method.
- (BOOL)textFieldShouldClear:(UITextField*)textField {
// Put your code in here.
return YES;
}
Edit: Setting the delegate on the textfield of a search bar in iOS8 will produce a crash. However it looks like the searchBar:textDidChange: method will get called on iOS8 on clear.