I'm new at this too but I think I can help. I did something similar. I set up a helper object to act as delegate for whatever view controller the user was currently interacting with. You'll write your code for making the toolbar appear. You'll implement those methods in the .m file of your helper (delegate) class. Add your helper class as an observer for the UIKeyboardDidShowNotification. So, in the viewDidLoad of my UIViewControllers, I set the delegate to my helper object. Then, when a keyboard appears on that current view controller, the notification is sent to the delegate (helper object).
Here's a little code to clarify:
In init method of helper object:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
Then, in the .m file of your helper object, in keyboardWasShown:, call [self makeToolbar] or whatever your methods are called. Sorry for the verbosity. Like I said, I'm pretty new but I hope this helps.
EDIT: So I made a simple little test/illustration. Here's the .h for my ViewController class. This is the ViewController that will contain the UITextFields, both of which bring up a keyboard and add a toolbar to it via a delegate method. Sorry for the lengthy response, but I thought it would be most useful to just give you all of what got it working for me.
#import <UIKit/UIKit.h>
#import "TextFieldDelegate.h"
@interface ViewController : UIViewController <UITextFieldDelegate> {
//Outlets for 2 UITextFields, added in IB. Selecting either will add the toolbar to your keyboard as long as the delegate is assigned and the methods in the delegate are implemented as shown.
IBOutlet UITextField *myTextField;
IBOutlet UITextField *myOtherTextField;
//we'll need to set the delegate for this class, so go ahead and declare a variable and make it a property (and synthesize it in the .m).
id delegate;
}
@property (nonatomic, strong) id delegate;
@end
ViewController.m:
@implementation ViewController
@synthesize delegate;
//removed method stubs and only left my modifications to the template.
- (void)viewDidLoad
{
[super viewDidLoad];
//create an instance of your delegate class and set it as the view controller's delegate.
//the text fields need their parent as the delegate, and the parent in turn assigns the helper class as its delegate.
//really this is the whole point, that you can just assign delegates to your view
//controllers and text fields and they can all access the one method implementation
//instead of each having to implement it separately themselves.
[myTextField setDelegate:self];
[myOtherTextField setDelegate:self];
TextFieldDelegate *myDelegate = [[TextFieldDelegate alloc] init];
[self setDelegate: myDelegate];
//set the delegate's currentViewController property so that we can add a subview to this View.
[delegate setCurrentViewController:self];
}
- (void)textFieldDidBeginEditing:(UITextField *)textField {
//set the delegate's current text field property so that we can resignFirstResponder.
[delegate setCurrentTextField:textField];
}
@end
Now here's the delegate class:
TextFieldDelegate.h:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface TextFieldDelegate : UIViewController <UITextFieldDelegate> {
UIViewController *currentViewController;
UITextField *currentTextField;
UIToolbar *keyboardToolbar;
CGSize kbSize;
}
- (void)loadToolbar;
@property (nonatomic, strong) UIViewController *currentViewController;
@property (nonatomic, strong) UITextField *currentTextField;
@end
And the implementation of the delegate:
TextFieldDelegate.m:
#import "TextFieldDelegate.h"
@implementation TextFieldDelegate
//synthesize properties so that View Controllers can set them as needed.
@synthesize currentViewController, currentTextField;
- (id)init {
self = [super init];
if (self) {
//register for the keyboard did show notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
}
return self;
}
- (void)keyboardWasShown:(NSNotification *)aNotification {
//get the keyboard size for positioning the toolbar. (depending on where you want it, I guess, I was just imagining it directly above the keyboard.
NSDictionary *info = [aNotification userInfo];
kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
//call the method to make the toolbar appear.
[self loadToolbar];
}
- (void)loadToolbar
{
if (keyboardToolbar == nil) {
//setting the position of the toolbar.
CGRect frameRect = self.view.frame;
frameRect.size.height -= kbSize.height;
keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, frameRect.size.height - 60.0, 320.0, 60.0)];
//your code for toolbar setup.
UIBarButtonItem *previousButton = [[UIBarButtonItem alloc] initWithTitle:@"Previous" style:UIBarButtonItemStyleBordered target:self action:@selector(previousField:)];
UIBarButtonItem *nextButton = [[UIBarButtonItem alloc] initWithTitle:@"Next" style:UIBarButtonItemStyleBordered target:self action:@selector(nextField:)];
UIBarButtonItem *extraSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(resignKeyboard:)];
[keyboardToolbar setItems:[[NSArray alloc] initWithObjects:previousButton, nextButton, extraSpace, doneButton, nil]];
//this line sends a message to the currently active view controller, telling it to add as a subview the toolbar that we have just created.
[[currentViewController view] addSubview:keyboardToolbar];
}
}
- (void)resignKeyboard:(id)sender {
[currentTextField resignFirstResponder];
[keyboardToolbar removeFromSuperview];
//set the toolbar to nil so that when you touch the other text field, it will build again.
keyboardToolbar = nil;
}
@end
So, there it is. Like I said, I'm new as well. But I hope this helps.
@jostster
EDIT: Oh, if you move the call to the custom delegate method loadToolbar into the ViewController's textFieldDidBeginEditing method, it works. In ViewController.m
- (void)textFieldDidBeginEditing:(UITextField *)textField {
//set the delegate's current text field property so that we can resignFirstResponder.
[delegate setCurrentTextField:textField];
[delegate loadToolbar];
}
And then you can just remove the [self loadToolbar] call from keyboardWasShown in the delegate implementation.
EDIT: to get your next and previous buttons working, first give your delegate a property: NSArray *textFieldArray. Then, in your view controller, create an array of your text fields (we'll call it tfArray), and then do [delegate setTextFieldArray:tfArray]; Then implement your previousField: and nextField: methods something like this:
- (void)previousField:(id)sender {
//get the index in the array of your currently active textField
int activeIndex = [textFieldArray indexOfObject:currentTextField];
//make sure you're not going to try to access an empty spot in the array
if (activeIndex > 0) {
UITextField *previousField = [textFieldArray objectAtIndex:activeIndex - 1];
[previousField becomeFirstResponder];
}
}
//same again but with a plus sign
- (void)nextField:(id)sender {
int activeIndex = [textFieldArray indexOfObject:currentTextField];
if (activeIndex < 1) {
UITextField *nextField = [textFieldArray objectAtIndex:activeIndex + 1];
[nextField becomeFirstResponder];
}
}
There might be a cleaner way to do this but the amount of code is so minimal that I don't feel like typing it twice is that big of a deal. That's the gist of it though and if you had a whole lot of text fields to advance through, you would just want to say something like:
if (activeIndex < [textFieldArray count]) {
//advance to the next textField
}