iPhone Application Development – Modal and Navigation View Controllers

Kanya Srinisavan
Tweet
This entry is part 5 of 10 in the series iPhone Application Development

iPhone Application Development

In my previous article, we created a list application using the table view controller. In this tutorial we will create a modal view controller to add items to the list and also view the details of each item by navigating to another view controller.

Open the ‘SampeListApp’ application.

Let us first modify the array that was used to populate the list and make it little more sensible.

Create a couple of dictionary with two items, keys being ‘Article’ and ‘Desc’ and objects being the name of the article and its description.

The array ‘arrItems’ that was used to populate the table view is no more a static array, as we will keep adding items to the array. So change it to ‘NSMutableArray’

The table view controller is inside a navigation controller. So we can set the title of the navigation bar with the help of the title property of the table view controller.

We can also access the navigation bar and navigation items from any of the view controllers that are added to the navigation controller stack.

We shall also change the tint color of the navigation bar and add a navigation item ‘+’ to it. We will add items to the list by capturing the click event of this navigation item.

After performing the changes mentioned above, your ‘viewDidLoad’ Method should look as follows:

SPTTableViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.title = @"Articles";

    self.navigationController.navigationBar.barTintColor = [UIColor redColor];

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addArticle)];

    NSDictionary *dictIosArticle1 = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:@"iOS Application: Getting Started", @"iOS Application:Getting Started Description",nil] forKeys:[NSArray arrayWithObjects:@"Article",@"Desc", nil]];
    NSDictionary *dictIosArticle2 = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:@"MVC And Programming Basics", @"MVC And Programming Basics Desc",nil] forKeys:[NSArray arrayWithObjects:@"Article",@"Desc", nil]];
    NSDictionary *dictIosArticle3 = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:@"View Controllers", @"View Controllers Desc",nil] forKeys:[NSArray arrayWithObjects:@"Article",@"Desc", nil]];

    arrItems = [[NSMutableArray alloc] initWithObjects:dictIosArticle1,dictIosArticle2,dictIosArticle3, nil];
}

Note that we have added a click event handler for the navigation item ‘Add’ and also set the target as ‘self’

We will see the method’s implementation in the later part of this tutorial.

Keep the number of sections in the tableview as 1.

Change the ‘cellForRowAtIndexPath’ method to display the name of the article. We will also change the font size and display a disclosure indicator to represent the navigation.

SPTTableViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
        
    NSDictionary *dictTmp = [arrItems objectAtIndex:indexPath.row];
    cell.textLabel.text = [dictTmp objectForKey:@"Article"];

    cell.textLabel.font = [UIFont boldSystemFontOfSize:12.0];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}

Let us implement two more protocol methods to display a title for the section. The table view style should be grouped for the section title to be visible.

SPTTableViewController.m

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return @"iOS";
} 
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 30.0f;
}

Now run the application in the iOS 7 simulator

ios simulator

Create a plain view controller ‘SPTArticleDetailViewController’ to display the description of the articles.

Place a ‘UITextView’ inside the view and map an outlet ‘txtDetails’ for it.

Try and make the text view non-editable and non-selectable with the help of the Attributes Inspector.

Create a string variable ‘strDesc’ using @property and @synthesize declarations to hold the description details in ‘SPTArticleDetailViewController’ class.

Set the title of this view controller in the ‘viewDidLoad’ Method

    self.title = @"Description";

The ‘txtDetails’ text should be the value of the string ‘strDesc’ which can be set in the ‘viewWillAppear’ method

SPTArticleDetailViewController.m

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:YES];
    self.txtDetails.text = strDesc;
}

The ‘strDesc’ value will be the article’s description and should be set in the ‘SPTTableViewController’ just before we push the ‘SPTArticleDetailViewController’ into the navigation stack.

The method ‘didSelectRowAtIndexpath’ in the ‘SPTTableViewController.m’ file, which is called on the selection of the list item, should be changed as follows.

SPTTableViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    
    SPTArticleDetailViewController *detailViewController = [[SPTArticleDetailViewController alloc] initWithNibName:@"SPTArticleDetailViewController" bundle:nil];
    
    // Pass the selected object to the new view controller.

    NSDictionary *dictTemp = [arrItems objectAtIndex:indexPath.row];
    detailViewController.strDesc = [dictTemp objectForKey:@"Desc"];
    
    // Push the view controller.
    [self.navigationController pushViewController:detailViewController animated:YES];
}

Don’t forget to import ‘SPTArticleDetailViewController’ header file in the ‘SPTTableViewController.m’ file. Otherwise, an error will be thrown.

The ‘pushViewController’ method helps in pushing the view controller to the navigation stack.

Run the Application in the simulator and select each list item. The details screen should look as given below

ios simulator

When you press the ‘Articles’ button, iOS automatically takes care of popping the currently visible view controller.

If there are so many levels of navigation and if you want to move directly to some view controller or the root view controller by removing all the top-level view controllers from the navigation stack, then the following two methods can be used.

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated; 
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated;

These methods return an array of popped view controllers.

Create one more view controller ‘ SPTAddArticleViewController’ as given below

file list window

Map outlets for the text fields.

We will place this view controller inside a navigation controller and add save and cancel buttons in the navigation bar.

Add button actions as well.

Create a protocol to save the article. We will delegate the save action to ‘SPTTableViewController’

Finally ‘SPTAddArticleViewController.h’ should look as given below

SPTAddArticleViewController.h

@protocol SPTAddArticleDelegate <NSObject>

-(void) addArticleName:(NSString *)strName andArticleDesc:(NSString *) strArticleDesc;

@end

@interface SPTAddArticleViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITextField *txtArticleName;
@property (weak, nonatomic) IBOutlet UITextField *txtArticleDesc;
@property (unsafe_unretained) id <SPTAddArticleDelegate> delegate;
- (void)saveAction;
- (void) cancelAction;
@end

Include @synthesize declaration for the delegate property.

Add the save and cancel buttons in the ‘viewDidLoad’ method

SPTAddArticleViewController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.title = @"Add Article";
    self.navigationController.navigationBar.barTintColor = [UIColor redColor];
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelAction)];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveAction)];
}

Now change the save and cancel action as follows. Look at how the action is delegated in the ‘saveAction’ method.

SPTAddArticleViewController.m

- (void)saveAction {
    
    [self dismissViewControllerAnimated:YES completion:nil];
    
    if((![self.txtArticleName.text isEqualToString:@""]) &&(![self.txtArticleDesc.text isEqualToString:@""]))
    {
        if([self.delegate respondsToSelector:@selector(addArticleName:andArticleDesc:)])
        {
            [self.delegate addArticleName:self.txtArticleName.text andArticleDesc:self.txtArticleDesc.text];
        }
    }
}

- (void)cancelAction{
    [self dismissViewControllerAnimated:YES completion:nil];

}

The method ‘dismissViewController’ is used to dismiss the presented view controller ‘SPTAddArticleViewController’

The ‘SPTTableViewController’ class should adopt the protocol as shown below

SPTTableViewController.h

#import "SPTAddArticleViewController.h"

@interface SPTTableViewController : UITableViewController<SPTAddArticleDelegate>
@property (nonatomic,strong) NSMutableArray *arrItems;
@end

In the ‘SPTTableViewController.m’ file create a private reference to ‘SPTAddArticleViewController’

SPTTableViewController.m

@interface SPTTableViewController ()

@property(nonatomic,strong) SPTAddArticleViewController *addController;

@end

@implementation SPTTableViewController
@synthesize arrItems,addController;

Implement the protocol method

SPTTableViewController.m

-(void) addArticleName:(NSString *)strName andArticleDesc:(NSString *) strArticleDesc
{
    NSMutableDictionary *mutDict = [[NSMutableDictionary alloc] init];
    [mutDict setObject:strName forKey:@"Article"];
    [mutDict setObject:strArticleDesc forKey:@"Desc"];
    [arrItems addObject:mutDict];
    [self.tableView reloadData];
}

The method ‘reloadData’ helps to reload the table view with the new data source or the modified array.

Final step is to present the ‘SPTAddArticleController’ on click of the ‘+’ or ‘Add’ button in the SPTTableViewController.

The ‘addArticle’ function should be implemented to bid adieu to this tutorial

SPTTableViewController.m

-(void) addArticle
{
    addController = [[SPTAddArticleViewController alloc] initWithNibName:@"SPTAddArticleViewController" bundle:nil];
    addController.delegate = self;

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addController];
    
    [self presentViewController:navController animated:YES completion:nil];
}

The controller has declared itself as the delegate of the ‘SPTAddArticleViewController’

The method ‘presentViewController’ helps in presenting a modal view controller.

Run the application in the simulator, click on the Add button and check this modal view controller.

ios simulator

Conclusion

As we reach the end of this tutorial, I hope you are clearer on some of the concepts in iOS.

You can download full code samples here.

We’ll explore another interesting topic in my next article.

iPhone Application Development

<< iPhone Application Development – Table View ControllersiPhone Application Development – Storyboards >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments