Who writes this stuff…
In: Tech
13 Jan 2010This will be the first simple tutorial covering some of the new things I am tackling as I build my first iPhone app. Today I want to go over creating a table view that will show a list of favorites that the user has already selected; this will basically mimic the “Favorites” Tab in the Phone app. I am going to keep this one simple, so there will be no adding of Favorites this time… that can be for another time.
Here is what we want to accomplish(with Editing mode on the right):


On to the code… lets start out by looking at the FavoritesViewController.h:
@interface FavoritesViewController : UIViewController <UITableViewDataSource> {
NSMutableArray *favorites;
UITableView *myTableView;
UINavigationItem *navItem;
UIBarButtonItem *editButton;
UIBarButtonItem *addButton;
}
@property(nonatomic,retain) IBOutlet UIBarButtonItem *addButton;
@property(nonatomic,retain) IBOutlet UIBarButtonItem *editButton;
@property(nonatomic,retain) IBOutlet UINavigationItem *navItem;
@property(nonatomic,retain) IBOutlet UITableView *myTableView;
@property(nonatomic,retain) NSMutableArray *favorites;
-(IBAction) addClicked:(id)sender;
-(IBAction) editClicked:(id)sender;
@end
The ‘favorites’ array is the DataSource for the myTableView object. The navItem is the bar at the top of the screen that shows our “Favorites” label and holds the editButton and addButton; I made these IBOutlets so I could set them in Interface Builder. The 2 IBActions will fire when their respective buttons are pressed… lets focus on the editClicked method. When the user presses the Edit button, we want to tell the TableView to go into editing-mode and then update the buttons to show their correct state.
-(IBAction) editClicked:(id)sender {
[self.myTableView setEditing:YES animated:YES];
UIBarButtonItem *doneButton =
[[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:@selector(doneEditingTable)];
navItem.leftBarButtonItem = doneButton;
navItem.rightBarButtonItem = nil;
[doneButton release];
}
Pretty simple stuff right!… When the User presses the newly created “Done” button, the doneEditingTable method will fire so we can deal with the clean up. Before that happens though, the user will probably want to actually delete a row. The framework will handle all of the animation that happens when the user presses the little circle to the left of the text. UPDATE: I found an easier implementation for the Edit/Done button… check out my short post.
After the “Delete” button is hit, the commitEditingStyle method is called so you will need to override it:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
UserDataService *dataService = [(BusTrackerAppDelegate*)[UIApplication sharedApplication].delegate userDataService];
FavoriteStop *favorite = [favorites objectAtIndex:indexPath.row];
[dataService deleteFavorite:favorite];
// Update the array and table view.
[favorites removeObjectAtIndex:indexPath.row];
[self.myTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
}
}
As you can see, first I need to delete the FavoriteStop object from my db via my UserDataService. After the service method successfully finishes the deletion, the TableView needs to be updated to reflect the new list of favorites. Instead of reloading all of the data for the list, you can just delete the corresponding row from the table’s data source and TableView. When the user is ready to finish deleting, they hit the “Done” button which fires an action to the doneEditingTable method. The only thing left to do in order to get back to the “Normal” state (like when the view first loaded) is to reset the buttons.
- (void) doneEditingTable {
[self.myTableView setEditing:NO animated:YES];
navItem.leftBarButtonItem = editButton;
navItem.rightBarButtonItem = addButton;
}
I had to keep a reference to the original buttons on top because they were removed earlier, so I made sure to connect them in Interface Builder (see the interface editButton/addButton outlets). After that method finishes, the user is back to the original view… you are done!
Finally, if you want to add sorting to the edit view you only need to overload a few more methods:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
// if you want to prevent a specific row from moving
if (indexPath.row == 0) {
return NO;
}
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath {
FavoriteStop *favorite = [[self.myTableView objectAtIndex:sourceIndexPath.row]];
// update sort order in db
// ...........
[self.myTableView removeObjectAtIndex:sourceIndexPath.row];
[self.myTableView insertObject:favorite atIndex:destinationIndexPath.row];
}
There are more advanced ways to do this stuff, so check out the great doc on the apple dev site.
This is a blog... Done!