在编辑模式下,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(滑动删除)”功能,在表格行中向左滑动,应该可以看见一个红色的删除按钮,点击删除按钮也可以删除表格行。