The Table View Controller

The goal of this chapter is to create an initial implementation of the table view controller, and to update the application delegate to create and configure an instance of the table view controller.

This chapter sets up the table view, creating an instance of a navigation controller and a table view controller, and configuring the Core Location manager. This provides the architecture for the application. In the next chapter, you’ll use Core Data to manage the actual data.

It’s assumed that you’re already familiar with view controllers and table views; this chapter does not provide significant detail or explanation beyond that you need to understand the role of each of the components in the application. If any of this is too challenging, you should stop here and practice writing some more applications before continuing.

The application delegate is responsible for creating, configuring, and displaying a navigation controller and a table view controller.

The table view controller displays the array of event objects. To support this, the controller adds four properties to the basic table view controller:

Creating and Defining the RootViewController Class

First, create files for the new class.

>> In Xcode, create a new UITableViewController subclass; call it RootViewController. (Do not create a nib file.)

Next, add four properties, for the events array, the managed object context, the Core Location manager, and an Add button. The root view controller serves as the Core Location manager’s delegate, so it must adopt the CLLocationManagerDelegate protocol.

>> Replace the contents of the RootViewController header file with the following:

#import <CoreLocation/CoreLocation.h>
 
@interface RootViewController : UITableViewController <CLLocationManagerDelegate> {
 
    NSMutableArray *eventsArray;
    NSManagedObjectContext *managedObjectContext;
 
    CLLocationManager *locationManager;
    UIBarButtonItem *addButton;
}
 
@property (nonatomic, retain) NSMutableArray *eventsArray;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
 
@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, retain) UIBarButtonItem *addButton;
 
@end

Implementing the RootViewController Class

There are several parts to the initial implementation; you need to:

All the code described in the following sections goes into the @implementation block of the RootViewController class, replacing implementations provided by the template as appropriate. (Implementations for the table view data source methods are described later.)

Synthesize the Properties

>> Add these lines:

@synthesize eventsArray;
@synthesize managedObjectContext;
@synthesize addButton;
@synthesize locationManager;

Write the Accessor Method for the Core Location Manager

>> Create an accessor method to dynamically create the Core Location manager on demand:

- (CLLocationManager *)locationManager {
 
    if (locationManager != nil) {
        return locationManager;
    }
 
    locationManager = [[CLLocationManager alloc] init];
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
    locationManager.delegate = self;
 
    return locationManager;
}

Next, implement two delegate methods to enable and disable the Add button as appropriate. If the Core Location manager is generating updates, then enable the button; if the Core Location manager is failing, then disable the button.

>> Add the following two Core Location manager delegate methods:

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation {
    addButton.enabled = YES;
}
 
- (void)locationManager:(CLLocationManager *)manager
       didFailWithError:(NSError *)error {
    addButton.enabled = NO;
}

Implementing viewDidLoad

The viewDidLoad method needs to set up the Core Location manager and the Add and Edit buttons.

>> Replace the implementation of viewDidLoad with the following:

- (void)viewDidLoad {
 
    [super viewDidLoad];
 
    // Set the title.
    self.title = @"Locations";
 
    // Set up the buttons.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;
 
    addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
    target:self action:@selector(addEvent)];
    addButton.enabled = NO;
    self.navigationItem.rightBarButtonItem = addButton;
 
    // Start the location manager.
    [[self locationManager] startUpdatingLocation];
}

Implement Methods for Memory Management

>> Replace the existing implementations of viewDidUnload and dealloc. The implementation of viewDidUnload should relinquish ownership of anything created in viewDidLoad that can be recreated.

- (void)viewDidUnload {
    self.eventsArray = nil;
    self.locationManager = nil;
    self.addButton = nil;
}
 
- (void)dealloc {
    [managedObjectContext release];
    [eventsArray release];
    [locationManager release];
    [addButton release];
    [super dealloc];
}

Configuring the Application Delegate

The application delegate is responsible for creating and configuring the root view controller and a navigation controller to contain it.

Add the Navigation Controller Property

You need to add a property for the navigation controller.

>> In the application delegate’s header file (LocationsAppDelegate.h), add an instance variable:

UINavigationController *navigationController;

>> Add the property declaration:

@property (nonatomic, retain) UINavigationController *navigationController;

Implement the Application Delegate

In the application delegate’s implementation file (LocationsAppDelegate.m), you need to:

  • Import the RootViewController’s header file.

  • Synthesize the navigationController property.

  • In the applicationDidFinishLaunching: method, create an instance of RootViewController and a navigation controller to contain it.

    You also need to pass the application’s managed object context to the new root view controller.

>> Before the @implementation block of the application delegate class, import the RootViewController class’s header file:

#import "RootViewController.h"

>> In the @implementation block of the application delegate class, synthesize the navigation controller property:

@synthesize navigationController;

>> Replace your application delegate’s application:didFinishLaunchingWithOptions: method with the following implementation:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
 
    RootViewController *rootViewController = [[RootViewController alloc]
    initWithStyle:UITableViewStylePlain];
 
    NSManagedObjectContext *context = [self managedObjectContext];
    if (!context) {
        // Handle the error.
    }
    // Pass the managed object context to the view controller.
    rootViewController.managedObjectContext = context;
 
    UINavigationController *aNavigationController = [[UINavigationController alloc]
    initWithRootViewController:rootViewController];
    self.navigationController = aNavigationController;
 
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];
 
    [rootViewController release];
    [aNavigationController release];
 
    return YES;
}

Build and Test

At this stage you should build and run the project to make sure that it all works.

When it launches, the application should display a blank table view with a navigation bar. The navigation bar should contain the Edit and Add buttons:

image: ../Art/initialApp.jpg

The Add button will initially be disabled, but after a few seconds it should become enabled (as the location manager starts sending events). If you tap it, the application will of course crash since you haven’t yet implemented the addEvent method. Before you can add an event, though, you need to define the Event entity. That’s what you’ll do next.


Did this document help you? Yes It's good, but... Not helpful...