So far, you’ve used the bundle template to set up preferences for the workshop’s UserPreferences application. The user can access and update them via the system’s Settings application. Now, in this workshop you will add code in the AppDelegate files to set up the application’s data model, design the FirstViewController nib file’s user interface, and code in the FirstViewController class files.
I want you to click the AppDelegate.h file add this code.
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate> @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) UITabBarController *tabBarController; // This variable will hold the path to the plist file @property (nonatomic, retain) NSString *dataFilePath; // This mutable array will hold content of the plist file @property (nonatomic, retain) NSMutableArray *booksArray; // This method will access the Application sandbox's Documents folder - (NSString *) documentsPath; // This method writes content of the booksArray to the booksOwned.plist file - (void) WriteBookInfoToFile; @end
Switch to the AppDelegate.m file and modify the top portion of the file’s code to what’s shown below.
#import "AppDelegate.h" #import "FirstViewController.h" #import "SecondViewController.h" @implementation AppDelegate - (NSString *) documentsPath { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [paths objectAtIndex:0]; // Return the Documents folder return documentsDir; } - (void) WriteBookInfoToFile { // Get the path to the plist file, from the Documents folder, then assign it to a variable self.dataFilePath = [self.documentsPath stringByAppendingPathComponent:@"booksOwned.plist"]; // Write entries stored in the booksArray to the booksOwned.plist file [self.booksArray writeToFile:self.dataFilePath atomically:YES]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Formulate the property list filename self.dataFilePath = [self.documentsPath stringByAppendingPathComponent:@"booksOwned.plist"]; // Check if the plist file exists if ([[NSFileManager defaultManager] fileExistsAtPath:self.dataFilePath]) { // It does, so load its content in the mutable array self.booksArray = [NSMutableArray arrayWithContentsOfFile:self.dataFilePath]; } else { // It doesn't, so create the booksOwn.plist file and initialize the booksArray variable self.booksArray = [[NSMutableArray alloc] init]; // Create 7 objects NSDictionary *book1 = [NSDictionary dictionaryWithObjectsAndKeys:@"Dead Until Dark", @"ktitle", @"Charlaine Harris", @"kauthor", nil]; NSDictionary *book2 = [NSDictionary dictionaryWithObjectsAndKeys:@"Using C++", @"ktitle", @"Julien Hennefeld", @"kauthor", nil]; NSDictionary *book3 = [NSDictionary dictionaryWithObjectsAndKeys:@"Think Like a Man, Act Like a Lady", @"ktitle", @"Steve Harvey", @"kauthor", nil]; NSDictionary *book4 = [NSDictionary dictionaryWithObjectsAndKeys:@"Visual Basic Objects", @"ktitle", @"John Smily", @"kauthor", nil]; NSDictionary *book5 = [NSDictionary dictionaryWithObjectsAndKeys:@"Javascript in Easy Steps", @"ktitle", @"Mike McGrath", @"kauthor", nil]; NSDictionary *book6 = [NSDictionary dictionaryWithObjectsAndKeys:@"Dead in The Family", @"ktitle", @"Charlaine Harris", @"kauthor", nil]; NSDictionary *book7 = [NSDictionary dictionaryWithObjectsAndKeys:@"Surrender to Marriage", @"ktitle", @"Iris Krasnow", @"kauthor", nil]; // Add 7 objects in the booksArray [self.booksArray addObject: book1]; [self.booksArray addObject: book2]; [self.booksArray addObject: book3]; [self.booksArray addObject: book4]; [self.booksArray addObject: book5]; [self.booksArray addObject: book6]; [self.booksArray addObject: book7]; // Write entries stored in the booksArray to the booksOwned.plist file [self.booksArray writeToFile:self.dataFilePath atomically:YES]; } // End of if statment // Initialize the app's window self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Initialize the tab bar's controllers UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:@"FirstViewController" bundle:nil]; UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil]; self.tabBarController = [[UITabBarController alloc] init]; self.tabBarController.viewControllers = @[viewController1, viewController2]; // Display the viewController1's view in the device's window self.window.rootViewController = self.tabBarController; [self.window makeKeyAndVisible]; return YES; }
What you did?
You added code in the AppDelegate files to create a plist file called booksOwned.plist in the application’s sandbox’sDocuments folder and added 7 book objects in it. By the way, code in the didFinishLaunchingWithOptions: method’s else block is only executed the very first time the application is launched.
Design The Book List View
I want you to replace controls the template placed on the FirstViewController nib’s user interface with a tableView control. Don’t forget to connect its dataSource and delegate to the File’s Owner object, via Interface Builder.
Populate The tableView Control Rows
I want you to add code shown below in the FirstViewController files to populate the tableView control’s rows with content stored in the booksOwned.plist file.
FirstViewController.h | FirstViewController.m |
---|---|
#import <UIKit/UIKit.h> @interface FirstViewController : UIViewController // This variable will hold content of the plist file @property (nonatomic, strong) NSMutableArray *booksArray; @end |
#import "AppDelegate.h" #import "FirstViewController.h" @implementation FirstViewController - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Set the tab bar's title self.title = @"Book List"; // set the tab bar's image self.tabBarItem.image = [UIImage imageNamed:@"96-book"]; } return self; } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; // Create an object of the delegate so we can use its variables and methods AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; if ([[NSFileManager defaultManager] fileExistsAtPath:delegate.dataFilePath]) { // Copy the delegate's booksArray to this class' own self.booksArray = delegate.booksArray; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end |
Now, add this code just above the @end keyword in the FirstViewController.m file
#pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [self.booksArray count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; } // Create a dictionary object and add the object stored in the booksArray that matches the table's indexPath row number in it NSDictionary *book = [self.booksArray objectAtIndex: [indexPath row]]; // Set the table row's text and textLabel property cell.textLabel.text = [book objectForKey:@"ktitle"]; cell.detailTextLabel.text = [book objectForKey:@"kauthor"]; return cell; }
After entering above code in the FirstViewController files, run the application to see this output in the iPhone Simulator.
That’s all for this week’s workshop. Next week, you will design second tab’s user interface and code in its class files it. Until then, happy coding! 🙂