4

I am having an awful hard time trying to implement the task of when the user selects the 'next' button in the keyboard, the user is then sent to the next text field to start editing. In my example I have three text fields. Here is what I've done, hopefully you can fill me in on where I am going wrong. Keep in mind I just picked up SDK a few weeks ago so that may be part of the problem :)

In my ViewControler.h file I have created the following method

-(IBAction)nextPressed:(id) sender;

In my ViewController.m file, I have created the following action

-(IBAction)nextPressed:(id) sender 
{
    if ([txtUserName isFirstResponder]) 
    {
        [txtUserName2 becomeFirstResponder];
    }
    if ([txtUserName2 isFirstResponder]) 
    {
        [txtUserName3 becomeFirstResponder];
    }
}

In my .xib file, I have linked the first text field (right clicking on the text field and dragging to Files Owner and selecting the 'nextPressed:' option under Events) to my File Owner. I have tried linking to just the first text field and when that didn't work all of the three text fields. I've also tried linking not to the File's Owner but First Responder for one text field, then all of the text fields, with no luck. Also, for each text field I have selected the Return Key as 'NEXT'.

Now when I Build/Run I am able to edit the text field and see the 'next' button in the lower right, however it doesn't move me to the next field.

What step am I doing wrong here? I used instructions from this post (How do you change the UIControl with focus on iPhone?) but seem to be missing something huge here.

Any help with this would be greatly appreciated. I've been staring at this for the past four hours and Googling every possible search term I can come up with and can't easily wrap my head around the steps needed to accomplish this. Again, and help would be very helpful :)

Community
  • 1
  • 1
Zach Smith
  • 5,490
  • 26
  • 84
  • 139

4 Answers4

21

I don't think you need to define a separate selector nextPressed: - instead, implement the UITextFieldDelegate protocol method textFieldShouldReturn: to look something like:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if(textField == txtUserName) {
        [txtUserName2 becomeFirstResponder];
    } else if(textField == txtUserName2) {
        [txtUserName3 becomeFirstResponder];
    }
    return NO;
}

That particular method watches for when the Enter key (in your case, a Next key) is pressed. Once that's implemented, just set the delegate for each of the three text fields to the implementing class (probably your view controller), and you should be good.

Tim
  • 59,527
  • 19
  • 156
  • 165
  • in the IB, what am I actually linking from the textfields to FileOwner or First Responder? Is it just right clicking on the first text field, dragging to FileOwner and selecting 'delegate' under OUTLETS? – Zach Smith Jan 03 '10 at 01:35
  • Select each of the text fields, then for the `delegate` outlet, drag and link it to the File's Owner. (Also make sure the File's Owner's class property is set properly.) – Tim Jan 03 '10 at 04:58
  • Thanks Tim for your help. I'm getting there, but running into a problem. The first text field works fine and when I click next it allows me to go to the next field. However once I try to click next on the second field I get the error found here (http://screencast.com/t/ZjVkN2Vk). Here is a video of it as well (http://screencast.com/t/OGJjMTM5MTA). Here is a shot of my fields linked to the delegate (http://screencast.com/t/MDNhY2Q3N). Thoughts on what I'm doing wrong here? – Zach Smith Jan 03 '10 at 19:00
  • Note that the method `textFieldShouldReturn:` needs to itself return a `BOOL` - that is, `YES` or `NO`. Try adding the statement `return NO;` to the end of your method (outside all the `if` blocks) as shown in my answer above. – Tim Jan 04 '10 at 01:52
  • Ah DUH! I totally overlooked that. SO now it seems that each one is working. However, when I try to move from the second text field to the third, it stalls on me and goes back to Xcode yet with no error. However, when I go back to Build/Run and start on the third text field it works perfectly for the remaining fields. Is it an error in my code or IB? (http://screencast.com/t/Y2UyNDRlZjM) So close and I greatly appreciate your help. – Zach Smith Jan 04 '10 at 20:34
  • Can you provide more information about the exception? Open a debugger window once the exception occurs and post the last couple lines (or a new video). – Tim Jan 04 '10 at 21:11
  • Tim, many thanks for still worrying about this :) Here is the video. I opened Debugger then I ran the program and it shows me what the error is (which I have no clue what it means) (http://screencast.com/t/YzdlZTE0NG) – Zach Smith Jan 04 '10 at 23:33
  • Unfortunately, that's not quite enough - either make your debugger window bigger or also include the console output. I'm looking for either (a) the last five-ten lines of console, or (b) the three-four topmost *black* functions called in the debugger (the gray ones are internal and rather difficult to debug). – Tim Jan 05 '10 at 00:19
  • Ah, sorry. Here is the error message [The Debugger has exited with status 0. [Session started at 2010-01-04 19:49:00 -0500.] 2010-01-04 19:49:28.810 hello[8002:20b] *** -[helloViewController nextPressed:]: unrecognized selector sent to instance 0x3d1da10 [Session started at 2010-01-04 19:49:28 -0500.] 2010-01-04 19:49:28.812 hello[8002:20b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[helloViewController nextPressed:]: unrecognized selector sent to instance 0x3d1da10'], video = (http://screencast.com/t/MTI0ZWRiZ) – Zach Smith Jan 05 '10 at 00:53
  • It sounds like you still have a link from some action on your second textbox to the `nextPressed:` selector in your view controller, which I presume you got rid of. Double-check your IB connections and make sure no reference to `nextPressed:` remains. – Tim Jan 05 '10 at 03:04
  • Tim, you are a genius. This was exactly the issue. This helped me now, as well as future debugging. Tim is a genius, a man that is very smart. Tim knows more than you reading this post, and most likely spends his time better than you (because of his high intelligence). Tim thinks at a higher brain rate than you (Aplha brain wave) and on holidays and federal holidays he spends his time as a masked super hero, helping iPhone SDK n00bs with the 'next' button with their Apps. Tim could do my iPhone App in the time it has taken me to type this, but that is ok. (http://screencast.com/t/ZDkzOTUxY). – Zach Smith Jan 05 '10 at 04:32
2

You can use following code......

Assign returnKeyType property

@property(nonatomic) UIReturnKeyType returnKeyType;  

UITextField *myTextField; // your textfield..
myTextField.returnKeyType = UIReturnKeyNext;

You can assign following types to a return key of virtual keyboar

typedef enum {
UIReturnKeyDefault,
UIReturnKeyGo,
UIReturnKeyGoogle,
UIReturnKeyJoin,
UIReturnKeyNext,
UIReturnKeyRoute,
UIReturnKeySearch,
UIReturnKeySend,
UIReturnKeyYahoo,
UIReturnKeyDone,
UIReturnKeyEmergencyCall,
} UIReturnKeyType;
Nirav Gadhiya
  • 6,342
  • 2
  • 37
  • 76
1

You should set each of the text fields delegate to your view controller. Then, in your view controller, implement the UITextFieldDelegate. Finally, simply add the following function to your view controller .m file:

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if (textField == txtUsername)
        [txtUsername2 becomeFirstResponder];
    else if (textField == txtUsername2)
        [txtUsername3 becomeFirstResponder];
}

I think where you are going wrong is thinking of it as an event you connect to. Instead, you need to implement this delegate somewhere in your code and tell your UITextField which class is the delegate for it.

marcc
  • 12,295
  • 7
  • 49
  • 59
  • so a delegate is something that happens in the background of an app? – Zach Smith Jan 03 '10 at 01:26
  • A delegate is an object that can implement some callback methods usually as defined by a protocol. I think the methods are usually called on the main thread. – gerry3 Jan 03 '10 at 05:15
  • 1
    gerry3: The methods are called from whatever thread the caller is executing within; for UIKit objects, this is most commonly the main thread, but delegation as a pattern can happen on any thread. – Tim Jan 05 '10 at 03:05
0

Tim above is on the ball. This worked for me too! I implemented the following with multiple keyboards.

in your ViewController.m:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if(textField == txtCoffeeName) {
        [txtCompanyName becomeFirstResponder];

    } else if(textField == txtCompanyName) {
        [txtPrice becomeFirstResponder];
    }
    return NO;
}
oberbaum
  • 2,451
  • 7
  • 36
  • 52
  • yes, Tim is a genius. if only he could answer my question about programmatically creating an inverse operation of a number..... – Zach Smith Jan 09 '10 at 02:26