Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Beginning iOS5 Development.pdf
Скачиваний:
7
Добавлен:
09.05.2015
Размер:
15.6 Mб
Скачать

304

CHAPTER 9: Navigation Controllers and Table Views

Figure 9–13. The detail view

Notice that when you drill down to the detail view, the title again changes, as does the back button, which now takes you to the previous view instead of the root view.

That finishes up the first view controller. Do you see now how the design Apple used here with the navigation controller makes it possible to build your application in small chunks? That’s pretty cool, isn’t it?

Second Subcontroller: The Checklist

The next second-level view we’re going to implement is another table view. But this time, we’ll use the accessory icon to let the user select one and only one item from the list. We’ll use the accessory icon to place a check mark next to the currently selected row, and we’ll change the selection when the user touches another row.

Since this view is a table view and it has no detail view, we don’t need a new nib, but we do need to create another subclass of BIDSecondLevelViewController. Select the Nav folder in the project navigator in Xcode, and then select File New New File. . . or pressN. Select Cocoa Touch on the left, Objective-C class on the right, and click Next. Then name your new class BIDCheckListController, enter BIDSecondLevelViewController for

Subclass of, and click the Next button. On the final screen, make sure the Nav folder, Group, and Target are selected (just as you’ve done for the other classes in this project).

www.it-ebooks.info

CHAPTER 9: Navigation Controllers and Table Views

305

Creating the Checklist View

To present a checklist, we need a way to keep track of which row is currently selected. We’ll declare an NSIndexPath property to track the last row selected. Single-click BIDCheckListController.h, and make the following changes:

#import "BIDSecondLevelViewController.h"

@interface BIDCheckListController : BIDSecondLevelViewController

@property (strong, nonatomic) NSArray *list;

@property (strong, nonatomic) NSIndexPath *lastIndexPath;

@end

Then switch over to BIDCheckListController.m, and add the following code:

#import "BIDCheckListController.h"

@implementation BIDCheckListController

@synthesize list; @synthesize lastIndexPath;

- (void)viewDidLoad { [super viewDidLoad];

NSArray *array = [[NSArray alloc] initWithObjects:@"Who Hash", @"Bubba Gump Shrimp Étouffée", @"Who Pudding", @"Scooby Snacks", @"Everlasting Gobstopper", @"Green Eggs and Ham", @"Soylent Green",

@"Hard Tack", @"Lembas Bread", @"Roast Beast", @"Blancmange", nil]; self.list = array;

}

- (void)viewDidUnload { [super viewDidUnload]; self.list = nil; self.lastIndexPath = nil;

}

#pragma mark -

#pragma mark Table Data Source Methods

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

return [list count];

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CheckMarkCellIdentifier = @"CheckMarkCellIdentifier";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CheckMarkCellIdentifier];

if (cell == nil) {

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CheckMarkCellIdentifier];

www.it-ebooks.info

306

CHAPTER 9: Navigation Controllers and Table Views

}

NSUInteger row = [indexPath row]; NSUInteger oldRow = [lastIndexPath row];

cell.textLabel.text = [list objectAtIndex:row]; cell.accessoryType = (row == oldRow && lastIndexPath != nil) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;

return cell;

}

#pragma mark -

#pragma mark Table Delegate Methods

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

int newRow = [indexPath row];

int oldRow = (lastIndexPath != nil) ? [lastIndexPath row] : -1;

if (newRow != oldRow) {

UITableViewCell *newCell = [tableView cellForRowAtIndexPath: indexPath];

newCell.accessoryType = UITableViewCellAccessoryCheckmark;

UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];

oldCell.accessoryType = UITableViewCellAccessoryNone; lastIndexPath = indexPath;

}

[tableView deselectRowAtIndexPath:indexPath animated:YES];

}

@end

Let’s start with the tableView:cellForRowAtIndexPath: method, which has a few new things worth noticing. The first several lines should be familiar to you.

static NSString *CheckMarkCellIdentifier = @"CheckMarkCellIdentifier";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CheckMarkCellIdentifier];

if (cell == nil) {

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CheckMarkCellIdentifier];

}

Next is where things get interesting. First, we extract the row from this cell and from the current selection.

NSUInteger row = [indexPath row];

NSUInteger oldRow = [lastIndexPath row];

We grab the value for this row from our array and assign it to the cell’s title.

cell.textLabel.text = [list objectAtIndex:row];

Then we set the accessory to show either a check mark or nothing, depending on whether the two rows are the same. In other words, if the table is requesting a cell for a

www.it-ebooks.info

CHAPTER 9: Navigation Controllers and Table Views

307

row that is the currently selected row, we set the accessory icon to be a check mark; otherwise, we set it to be nothing. Notice that we also check lastIndexPath to make sure it’s not nil. We do this because a nil lastIndexPath indicates no selection.

However, calling the row method on a nil object will return a 0, which is a valid row, but we don’t want to put a check mark on row 0 when, in reality, there is no selection.

cell.accessoryType = (row == oldRow && lastIndexPath != nil) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;

Now skip down to the last method. You’ve seen the tableView:didSelectRowAtIndexPath: method before, but we’re doing something new here. We grab not only the row that was just selected, but also the row that was previously selected.

int newRow = [indexPath row];

int oldRow = [lastIndexPath row];

We do this so if the new row and the old row are the same, we don’t bother making any changes.

if (newRow != oldRow) {

Next, we grab the cell that was just selected and assign a check mark as its accessory icon.

UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];

newCell.accessoryType = UITableViewCellAccessoryCheckmark;

We then grab the previously selected cell, and we set its accessory icon to none.

UITableViewCell *oldCell = [tableView cellForRowAtIndexPath: lastIndexPath];

oldCell.accessoryType = UITableViewCellAccessoryNone;

After that, we store the index path that was just selected in lastIndexPath, so we’ll have it the next time a row is selected.

lastIndexPath = indexPath;

}

When we’re finished, we tell the table view to deselect the row that was just selected, because we don’t want the row to stay highlighted. We’ve already marked the row with a check mark, so leaving it blue would just be a distraction.

[tableView deselectRowAtIndexPath:indexPath animated:YES];

}

Adding a Checklist Controller Instance

Our next task is to add an instance of this controller to BIDFirstLevelController‘s controllers array. Start off by importing the new header file, adding this line just after all the other #import statements at the top of the file:

#import "BIDCheckListController.h"

www.it-ebooks.info

308

CHAPTER 9: Navigation Controllers and Table Views

Then create an instance of BIDCheckListController by adding the following code to the viewDidLoad method in BIDFirstLevelController.m:

- (void)viewDidLoad { [super viewDidLoad];

self.title = @"First Level";

NSMutableArray *array = [[NSMutableArray alloc] init];

// Disclosure Button

BIDDisclosureButtonController *BIDDisclosureButtonController = [[BIDDisclosureButtonController alloc] initWithStyle:UITableViewStylePlain];

BIDDisclosureButtonController.title = @"Disclosure Buttons"; BIDDisclosureButtonController.rowImage = [UIImage imageNamed:

@"BIDDisclosureButtonControllerIcon.png"]; [array addObject:BIDDisclosureButtonController];

// Checklist

BIDCheckListController *checkListController = [[BIDCheckListController alloc] initWithStyle:UITableViewStylePlain];

checkListController.title = @"Check One"; checkListController.rowImage = [UIImage imageNamed:

@"checkmarkControllerIcon.png"]; [array addObject:checkListController];

self.controllers = array;

}

Well, what are you waiting for? Save your changes, compile, and run. If everything went smoothly, the application launched again in the simulator, and there was much rejoicing. This time there will be two rows (see Figure 9–14).

www.it-ebooks.info

CHAPTER 9: Navigation Controllers and Table Views

309

Figure 9–14. Two second-level controllers and two rows. What a coincidence!

If you touch the Check One row, it will take you down to the view controller we just implemented (see Figure 9–15). When it first comes up, no rows will be selected and no check marks will be visible. If you tap a row, a check mark will appear. If you then tap a different row, the check mark will switch to the new row. Huzzah!

www.it-ebooks.info

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]