UITableVIew and UITableViewController

UITableView is a view object, so, according to Model-View-Controller, it knows how to draw itself, but that's it.

UITableView needs a data source to ask for data, a delegate to inform events involving the UITableView, and typically a view controller to create and destroy instance of UITableView.

a singleton

#import <Foundation/Foundation.h>
@interface PossessionStore : NSObject
{
}
// Notice that this is a class method, and is prefixed with a + instead of a -
+ (PossessionStore *)defaultStore;
@end

at the top of .m file, create a global static variable to hold the instance variable.

#import "PossessionStore.h"
#import "Possession.h"
static PossessionStore *defaultStore = nil;
@implementation PossessionStore

Also, in .m file, implement +defaultStore, +allocWithZone: and -init so that only one instance of the class can be created.

+ (PossessionStore *)defaultStore
{
if (!defaultStore) {
// Create the singleton
defaultStore = [[super allocWithZone:NULL] init];
}
return defaultStore;
}
// Prevent creation of additional instances
+ (id)allocWithZone:(NSZone *)zone
{
return [self defaultStore];
}
- (id)init
{
// If we already have an instance of PossessionStore...
if (defaultStore) {
// Return the old one
return defaultStore;
}
self = [super init];
return self;
}

Now, override the retain count methods so that no one can release the defaultStore.

- (id)retain
{
// Do nothing
return self;
}
- (void)release
{
// Do nothing
}
- (NSUInteger)retainCount
{
return NSUIntegerMax;
}

Now you have a singleton.

Reuse UITableViewCell

- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Check for a reusable cell first, use that if it exists
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
// If there is no reusable cell of this type, create a new one
if (!cell) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:@"UITableViewCell"] autorelease];
}
Possession *p = [[[PossessionStore defaultStore] allPossessions]
objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[p description]];
return cell;
}

Editing Mode

UITableView has an editing property, and when this property is set to YES, the UITableView enters editing mode. Editing mode does not allow the user to edit the content of a row.

In the toggleEditingMode: method, you could toggle the editing property of UITableView directly. However, UITableViewController also has an editing property. A UITableViewController instance automatically sets the editing property of its table view to match its own editing property. Which one should you set? Follow the Model-View-Controller pattern: talke to the controller and let the controller talk to the view.

- (void)toggleEditingMode:(id)sender
{
// If we are currently in editing mode...
if ([self isEditing]) {
// Change text of button to inform user of state
[sender setTitle:@"Edit" forState:UIControlStateNormal];
// Turn off editing mode
[self setEditing:NO animated:YES];
} else {
// Change text of button to inform user of state
[sender setTitle:@"Done" forState:UIControlStateNormal];
// Enter editing mode
[self setEditing:YES animated:YES];
}
}

Adding Rows

We are going to put a New button in the header view to allow adding a row.

- (IBAction)addNewPossession:(id)sender
{
[[PossessionStore defaultStore] createPossession];
// tableView returns the controller's view
[[self tableView] reloadData];
}

Deleting Rows

Before the table view will delete a row, it sends its data source a message about the deletion and waits for confirmation before pulling the trigger.

delete from datasource, not just from UITableViewController.

- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // If the table view is asking to commit a delete command...
   if (editingStyle == UITableViewCellEditingStyleDelete)
   {
       PossessionStore *ps = [PossessionStore defaultStore];
       NSArray *possessions = [ps allPossessions];
       Possession *p = [possessions objectAtIndex:[indexPath row]];
       [ps removePossession:p];
       // We also remove that row from the table view with an animation
       [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
       withRowAnimation:YES];
   }
}

Moving Rows

you will use another method from the UITableViewDataSource protocol – tableView:moveRowAtIndexPath:toIndexPath:.

- (void)movePossessionAtIndex:(int)from
                     toIndex:(int)to
{
  if (from == to) {
    return;
  }
  // Get pointer to object being moved
  Possession *p = [allPossessions objectAtIndex:from];
  // Retain it... (retain count of p = 2)
  [p retain];
  // Remove p from array, it is automatically sent release (retain count of p = 1)
  [allPossessions removeObjectAtIndex:from];
  // Insert p in array at new location, retained by array (retain count of p = 2)
  [allPossessions insertObject:p atIndex:to];
  // Release p (retain count = 1, only owner is now array)
  [p release];
}

Now, in implement tableView:moveRowAtIndexPath:toIndexPath: to update the store.

- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
toIndexPath:(NSIndexPath *)toIndexPath
{
    [[PossessionStore defaultStore] movePossessionAtIndex:[fromIndexPath row]
                                                  toIndex:[toIndexPath row]];
}

 

 

posted on 2012-06-16 10:55  grep  阅读(1420)  评论(0编辑  收藏  举报