Text Input and Presenting Content Modally

A keyboard is presented automatically when a user selects a text container.  In IB you can select text input traits for your container.  Likewise the keyboard will be dismissed automatically when the user is finished with it.

When a user is being asked to pick or add data, often a view will be presented modally which means the user must take an action and then return back.  Presenting and dismissing a view modally is done with the methods:

    [self presentModalViewController: viewController animated:YES];

and

    [self dismissModalViewControllerAnimated:YES];

It is best practice for the same object to do both the call to present and dismiss.  A good way to achieve this is to define delegate methods for the presented controller which tell the delegate when the presented controller is done.  The parent controller is then made the delegate so that it can dismiss the controller at the appropriate time.

Here is an example.  We define a view controller which will present a  textField in which the user can type something.  This view controller defines a delegate protocol with the method -typeSomethingViewController: didTypeSomething: which will be implemented by the delegate a invoked when the typing is complete.  Also a delegate property is defined in the class.  Here is the header file:

      
        // TypeSomethingViewController.h
        #import <UIKit/UIKit.h>

        @protocol TypeSomethingViewControllerDelegate;

        @interface TypeSomethingViewController : UIViewController {
                UITextField *textField;
                id<TypeSomethingViewControllerDelegate> delegate;
        }

        @property (retain) IBOutlet UITextField *textField;
        @property (assign) id<TypeSomethingViewControllerDelegate> delegate;

        - (IBAction)doneButtonPressed:(id)sender;

        @end

        @protocol TypeSomethingViewControllerDelegate <NSObject>

        @optional

        - (void)typeSomethingViewController:(TypeSomethingViewController *)controller didTypeSomething:(NSString *)text;

        @end

Now in the implementation of the class we need to define the doneButtonPressed: method which will invoke the delegate method typeSomethingViewController: didTypeSomething: with the parameter values of itself and the text that was entered in the textField.  This method will be giving the text to the delegate after it is entered.  Here is the .m file:

        // TypeSomethingViewController.m
           #import "TypeSomethingViewController.h"

        @implementation TypeSomethingViewController

        @synthesize textField;
        @synthesize delegate;

        - (IBAction)doneButtonPressed:(id)sender{
                if ([self.delegate respondsToSelector:@selector(typeSomethingViewController:didTypeSomething:)]) {
                    [self.delegate typeSomethingViewController:self didTypeSomething:textField.text];
                }
        }

        - (void)dealloc {
            [textField release];
            [super dealloc];
        }

        @end

Now we will look at the parent controller which will present and dismiss the TypeSomethingViewController and will implement the TypeSomethingViewControllerDelegate.  Firstly the ParentViewController.h will need to specify that this class implements the TypeSomethingViewControllerDelegate. 

        // ParentViewController.h
        #import <UIKit/UIKit.h>
        #import "TypeSomethingViewController.h"

        @interface ParentViewController : UIViewController < TypeSomethingViewControllerDelegate> {

                . . .

        }
       
        . . .

        @end

Suppose the ParentViewController has a method showTypeSomething: where it is going to present the TypeSomethingViewController modally.  Within this method the parent will create a TypeSomethingViewController object, set itself as the delegate and present the view controller:

        - (IBAction)showTypeSomething:(id)sender {
                TypeSomethingViewController *typeSomethingViewController = [[TypeSomethingViewController alloc] init];
                typeSomethingViewController.delegate = self;
                [self presentModalViewController:typeSomethingViewController animated:YES];
                [typeSomethingViewController release];
        }

Finally the ParentViewController will need to implement the delegate method which will presumably do something with the text that was typed and dismiss the TypeSomethingViewController.

        - (void)typeSomethingViewController:(TypeSomethingViewController *)controller didTypeSomething:(NSString *)text {
                    typeSomethingLabel.text = text;
                    [self dismissModalViewControllerAnimated:YES];
        }