首页 » iOS编程(第4版) » iOS编程(第4版)全文在线阅读

《iOS编程(第4版)》9.3 删除行

关灯直达底部

在编辑模式下,UITableViewCell对象可能会显示中间有个减号的红色圆圈(见图9-8)。这个红色圆圈是删除控件(deletion control),按下删除控件可以删除其所属的那个表格行。但是Homepwner中的删除控件不会执行任何操作(请读者自己尝试)。这是因为UITableView对象在删除某一个表格行前,会先向数据源发送一条特定的消息,得到确认后才会有实际的操作。

要删除Homepwner中的某个表格行(UITableViewCell对象),必须执行两步:①从UITableView对象删除指定的UITableViewCell对象。②找到和需要删除的UITableViewCell对象对应的BNRItem对象,也将其从BNRItemStore中删除。为了完成第二步,BNRItemStore必须实现新的方法,用于移除指定的BNRItem对象。在BNRItemStore.h中声明新方法removeItem:,代码如下:

@interface BNRItemStore : NSObject

+ (BNRItemStore *)sharedStore;

@property (nonatomic, strong, readonly) NSArray *allItems;

- (BNRItem *)createItem;

- (void)removeItem:(BNRItem *)item;

@end

在BNRItemStore.m中实现removeItem:,代码如下:

- (void)removeItem:(BNRItem *)item

{

[self.privateItems removeObjectIdenticalTo:item];

}

removeItem方法调用了NSMutableArray的removeObjectIdenticalTo:。除了removeObjectIdenticalTo:,还可以使用removeObject:。这两个方法的差别是,removeObject:会枚举数组,向每一个对象发送isEqual:消息。isEqual:的作用是判断当前对象和传入对象所包含的数据是否相等(返回YES或NO)。不同的类可以根据自身情况覆盖isEqual:并实现相应的逻辑。以BNRItem为例,当两个BNRItem对象的valueInDollars相等时,可以认为这两个对象是相等的。

removeObjectIdenticalTo:方法不会比较对象所包含的数据,只会比较指向对象的指针。因此,该方法只会移除数组所保存的那些和传入对象指针完全相同的指针。虽然本章没有覆盖BNRItem的isEqual:来实现特殊的比较逻辑,但是将来可能会。因此,removeItem:方法应该使用removeObjectIdenticalTo:删除指定的BNRItem:对象。

接下来为BNRItemsViewController实现tableView:commitEditingStyle: forRowAtIndexPath:,该方法是UITableViewDataSource协议所声明的方法之一(UITableView对象会向BNRItemsViewController对象发送这个消息。注意:UITableView对象的数据源是BNRItemsViewController对象,而不是负责保存数据的BNRItemStore对象)。

UITableView对象在向其数据源发送tableView:commitEditingStyle: forRowAtIndexPath:消息时,会传入三个实参。第一个实参是发送该消息的UITableView对象。第二个实参是UITableViewCellEditingStyle类型的常数(删除表格行时,传入的是UITableViewCellEditingStyleDelete)。第三个实参是一个NSIndexPath对象,其中包含相应表格行所在的表格段索引和行索引。

在BNRItemsViewController.m中实现tableView:commitEditingStyle: forRowAtIndexPath:,先从BNRItemStore对象中删除相应的BNRItem对象,然后向UITableView对象发送deleteRowsAtIndexPaths:withRowAnimation:消息,删除表格视图中的相应表格行,代码如下:

- (void)tableView:(UITableView *)tableView

commitEditingStyle:(UITableViewCellEditingStyle)editingStyle

forRowAtIndexPath:(NSIndexPath *)indexPath

{

// 如果UITableView对象请求确认的是删除操作……

if (editingStyle == UITableViewCellEditingStyleDelete)

{

NSArray *items = [[BNRItemStore sharedStore] allItems];

BNRItem *item = items[indexPath.row];

[[BNRItemStore sharedStore] removeItem:item];

// 还要删除表格视图中的相应表格行(带动画效果)

[tableView deleteRowsAtIndexPaths:@[indexPath]

withRowAnimation:UITableViewRowAnimationFade];

}

}

构建并运行应用。先加入若干新行,然后删除其中的某个表格行,Homepwner的UITableView对象能正确地执行上述操作。最后请读者尝试“swipe-to-delete(滑动删除)”功能,在表格行中向左滑动,应该可以看见一个红色的删除按钮,点击删除按钮也可以删除表格行。