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
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
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
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.
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.