LISTING 7 - 4 continued Task* managedTaskObject; NSManagedObjectContext *managedObjectContext; } @property nonatomic, retain Task* managedTaskObject; @property nonatomic, retain NSMan
Trang 1LISTING 7 - 4 (continued)
Task* managedTaskObject;
NSManagedObjectContext *managedObjectContext;
}
@property (nonatomic, retain) Task* managedTaskObject;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@end
In the implementation fi le, you fi rst need to synthesize the properties that you declared in the
header:
@synthesize managedTaskObject,managedObjectContext;
As in the EditTextController , you should implement the viewDidUnload method to set the
properties defi ned in the class to nil :
- (void)viewDidUnload {
self.managedObjectContext=nil;
self.managedTaskObject = nil;
[super viewDidUnload];
}
EditPriorityController.m
Leave the numberOfSectionsInTableView method with the default implementation because the
table will have only one section Change tableView:numberOfRowsInSection: to return four
rows, one for each priority level
Next, implement the tableView:cellForRowAtIndexPath: method to show the priority options in
the appropriate cell:
// Customize the appearance of table view cells
- (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] autorelease];
}
Trang 2
// Set up the cell
switch (indexPath.row) { case 0:
cell.textLabel.text = @”None”;
break;
case 1:
cell.textLabel.text = @”Low”;
break;
case 2:
cell.textLabel.text = @”Medium”;
break;
case 3:
cell.textLabel.text = @”High”;
break;
default:
break;
} // place the checkmark next to the existing priority
if (indexPath.row == [managedTaskObject.priority intValue] ) {
cell.accessoryType=UITableViewCellAccessoryCheckmark;
} return cell;
}
EditPriorityController.m
This method should be familiar to you The fi rst few lines try to dequeue a cell as usual Then, the code determines the text of the cell based on which cell you are providing The last bit of code displays a checkmark next to the currently chosen priority for the task
When a user taps a row, you need to save that selection in the Task object You will do that in the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Deselect the currently selected row according to the HIG [tableView deselectRowAtIndexPath:indexPath animated:NO];
// Configure the managed object managedTaskObject.priority=[NSNumber numberWithInt:indexPath.row];
// Save the context
NSError *error = nil;
if (![self.managedObjectContext save: & error]) { // There was an error validating the date
Trang 3// Display error information
NSLog(@”Unresolved error %@, %@”, error, [error userInfo]);
UIAlertView* alert = [[UIAlertView alloc]
initWithTitle:@”Invalid Due Date”
message:[[error userInfo] valueForKey:@”ErrorString”]
delegate:nil cancelButtonTitle:@”OK” otherButtonTitles:nil ];
[alert show];
[alert release];
// Roll back the context to
// revert back to the old priority
[self.managedObjectContext rollback];
}
else {
// pop the view
[self.navigationController popViewControllerAnimated:YES];
}
}
EditPriorityController.m
The fi rst thing that this method does is deselect the selected row as I explained in the
last section
The next line sets the Task object ’ s priority fi eld to the priority level selected on the screen
Then, the code saves the context Because you are going to add a validation rule that includes the
priority, there is a possibility that the new priority could fail the validation If the validation fails,
the save method will fail, so you need to roll the context back to its state before the failed save
If the save method fails, you revert the priority back to its original state using the rollback
method of the context The rollback method undoes all changes to the context that have not yet
been committed with a successful save call If an error occurs, such as a validation failure, you
show the user an alert to inform him that a problem has occurred If there is no problem, the code
pops the View Controller from the stack
Finally, implement the dealloc method to release the member variables that you allocated in
the class:
- (void)dealloc {
[managedTaskObject release];
[managedObjectContext release];
[super dealloc];
}
EditPriorityController.m
Trang 4Adding and Editing Locations with the
EditLocationController
The user navigates to the EditLocationController by tapping the location cell on the ViewTaskController The
EditLocationController , as shown in Figure 7 - 9, allows the user to select a location, add new locations, and delete existing locations To create the EditLocationController , create a new UITableviewController without a NIB called
EditLocationController Modify your new header fi le to create instance variables and properties to hold the context and Task objects that the parent screen will confi gure You will also need to add a member variable and property for the NSFetchedResultsController that you will use to display your location list Additionally, you will need to add #import directives for the Task and
Location header fi les The completed header fi le should look like Listing 7 - 5
LISTING 7 - 5: EditLocationController.h
#import < UIKit/UIKit.h >
#import “Task.h”
#import “Location.h”
@interface EditLocationController : UITableViewController < NSFetchedResultsControllerDelegate >
NSFetchedResultsController *fetchedResultsController;
NSManagedObjectContext *managedObjectContext;
Task* managedTaskObject;
}
@property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain) Task* managedTaskObject;
@end
Let ’ s move on to the implementation fi le Add an import statement for EditTextController.h :
#import “EditTextController.h”
You will use the EditTextController to add the text for newly added locations Next, synthesize the properties that you declared in the header fi le:
@synthesize fetchedResultsController, managedObjectContext, managedTaskObject;
FIGURE 7 - 9: EditLocation Controller Screen
Trang 5Uncomment and implement the viewDidLoad method:
- (void)viewDidLoad {
[super viewDidLoad];
// Set up the add button
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self action:@selector(insertNewLocation)];
self.navigationItem.rightBarButtonItem = addButton;
[addButton release];
NSError* error;
if (![[self fetchedResultsController] performFetch: & error]) {
NSLog(@”Unresolved error %@, %@”, error, [error userInfo]);
abort();
}
// set the title to display in the nav bar
self.title = @”Location”;
}
EditLocationController.m
This code creates the addButton and sets it to call the insertNewLocation method It then adds the
addButton to the nav bar Next, you tell the fetched results controller to fetch its data Finally, you
set the title of the screen to Location
Next, you need to set the class properties in the viewDidUnload method to nil :
- (void)viewDidUnload {
self.fetchedResultsController=nil;
self.managedTaskObject=nil;
self.managedObjectContext=nil;
[super viewDidUnload];
}
EditLocationController.m
Now, add the insertNewLocation method that runs when the user taps the Add button that
you created in viewDidLoad This method adds a new Location to the context and pushes the
text controller on to the navigation stack to allow the user to edit the location name Here is
the insertNewLocation method:
- (void)insertNewLocation {
NSManagedObjectContext *context = self.managedObjectContext;
Location *newLocation =