iOS开发基础20-UITableView的全局及局部刷新、左滑操作与批量删除

UITableView 是 iOS 开发中广泛使用的组件,用于展示大量数据项。对于更好的用户体验,通常需要支持数据的动态更新、左滑操作和批量删除功能。本篇文章将详细介绍如何实现这些功能,并对背后的一些底层逻辑进行深入分析。

前期准备

项目初始化

  1. 创建项目:打开 Xcode,创建一个新的 iOS 项目。
  2. Storyboard 布局:在 Main.storyboard 中拖入一个 UITableView,并添加必要的约束。

数据模型和自定义 Cell 类

数据模型类 XMGWine

创建一个数据模型类 XMGWine,包含酒的相关属性。

#import <Foundation/Foundation.h>

@interface XMGWine : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *money;
@property (nonatomic, copy) NSString *image;
@property (nonatomic, assign, getter=isChecked) BOOL checked; // 用于自定义批量删除

@end

#import "XMGWine.h"

@implementation XMGWine

@end

自定义 Cell 类 XMGWineCell

创建一个自定义的 Cell 类 XMGWineCell,并在其 .xib 或者 storyboard 中实现基本布局。包括酒图片、名字和价格等。

#import <UIKit/UIKit.h>
#import "XMGWine.h"

@interface XMGWineCell : UITableViewCell

@property (nonatomic, strong) XMGWine *wine;

@end

#import "XMGWineCell.h"

@implementation XMGWineCell

- (void)setWine:(XMGWine *)wine {
    _wine = wine;
    self.textLabel.text = wine.name;
    self.detailTextLabel.text = wine.money;
    self.imageView.image = [UIImage imageNamed:wine.image];
    self.accessoryType = wine.isChecked ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
}

@end

懒加载数据

为了加载我们的初始数据,这里使用懒加载方法初始化一个 wineArray

#import "XMGWine.h"
#import "XMGWineCell.h"
#import "ViewController.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) NSMutableArray<XMGWine *> *wineArray;
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@end

@implementation ViewController

- (NSMutableArray<XMGWine *> *)wineArray {
    if (!_wineArray) {
        _wineArray = [NSMutableArray array];
        // 加载数据
        // 例如读取一个plist文件
        // _wineArray = [XMGWine objectArrayWithFilename:@"wines.plist"];
    }
    return _wineArray;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
}

@end

一、全局刷新

1. 添加单组数据并全局刷新

添加新的数据到数据模型,并使用 reloadData 全局刷新 UITableView

- (IBAction)add {
    XMGWine *wine = [[XMGWine alloc] init];
    wine.money = @"20.5";
    wine.name = @"很好喝的酒";
    wine.image = @"new_wine";
    [self.wineArray insertObject:wine atIndex:0];
    [self.tableView reloadData];
}

2. 删除单组数据并全局刷新

删除数据并全局刷新。

- (IBAction)remove {
    [self.wineArray removeObjectAtIndex:0];
    [self.tableView reloadData];
}

3. 更改数据并全局刷新

修改数据并全局刷新。

- (IBAction)update {
    XMGWine *wine = self.wineArray[0];
    wine.money = @"100";
    [self.tableView reloadData];
}

分析与优化

全局刷新 (reloadData) 是一个简单且粗暴的方法,它会重新加载整个列表,虽然简单,但效率低下。对于小数据集,全局刷新可能是可以接受的,但对于大型数据集,频繁的全局刷新是不现实的,会导致性能问题。

二、局部刷新

为了提高性能,我们可以借助 UITableView 的部分更新方法进行局部刷新。

1. 添加多组数据并局部刷新

在特定的索引处插入新的数据,同时只对这部分进行刷新。

- (IBAction)add {
    XMGWine *wine1 = [[XMGWine alloc] init];
    wine1.money = @"20.5";
    wine1.name = @"很好喝的酒";
    wine1.image = @"new_wine";
    [self.wineArray insertObject:wine1 atIndex:0];

    XMGWine *wine2 = [[XMGWine alloc] init];
    wine2.money = @"100.5";
    wine2.name = @"很好";
    wine2.image = @"new_wine";
    [self.wineArray insertObject:wine2 atIndex:0];

    NSArray *indexPaths = @[
        [NSIndexPath indexPathForRow:0 inSection:0],
        [NSIndexPath indexPathForRow:1 inSection:0]
    ];
    [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
}

2. 删除多组数据并局部刷新

删除特定的索引处的数据,同时只对这部分进行刷新。

- (IBAction)remove {
    [self.wineArray removeObjectAtIndex:0];
    [self.wineArray removeObjectAtIndex:0];
    
    NSArray *indexPaths = @[
        [NSIndexPath indexPathForRow:0 inSection:0],
        [NSIndexPath indexPathForRow:1 inSection:0]
    ];
    [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationMiddle];
}

3. 修改多项数据并局部刷新

更新特定索引的数据,同时只对这部分进行刷新。

- (IBAction)update {
    XMGWine *wine1 = self.wineArray[0];
    wine1.money = @"100";

    XMGWine *wine2 = self.wineArray[2];
    wine2.image = @"new_wine";

    XMGWine *wine3 = self.wineArray[3];
    wine3.image = @"new_wine";

    NSArray *indexPaths = @[
        [NSIndexPath indexPathForRow:0 inSection:0],
        [NSIndexPath indexPathForRow:2 inSection:0],
        [NSIndexPath indexPathForRow:3 inSection:0]
    ];
    [self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationLeft];
}

分析与优化

局部刷新即使用 insertRowsAtIndexPaths:withRowAnimation:deleteRowsAtIndexPaths:withRowAnimation:reloadRowsAtIndexPaths:withRowAnimation: 方法,可以显著提高性能,特别是在数据更新频繁的情况下。然而需要注意的是:

  • 保证数据源的更新和 UITableView 的更新保持一致性。
  • 合理选择动画效果,提升用户体验。

三、左滑操作

1. 删除功能

通过实现 commitEditingStyle:forRowAtIndexPath: 方法启用左滑删除功能。

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [self.wineArray removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
    }
}

2. 自定义删除按钮的文字

通过实现 tableView:titleForDeleteConfirmationButtonForRowAtIndexPath: 方法自定义删除按钮的文字。

- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath {
    return @"删除";
}

四、左滑出现更多按钮

可以通过 editActionsForRowAtIndexPath: 方法添加更多的左滑按钮。

- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewRowAction *actionFollow = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        NSLog(@"点击了关注");
        tableView.editing = NO;
    }];
    
    UITableViewRowAction *actionDelete = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        [self.wineArray removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }];

    return @[actionDelete, actionFollow];
}

五、进入编辑模式

通过设置 tableView.editing 属性让表格进入编辑模式。

- (IBAction)remove {
    [self.tableView setEditing:!self.tableView.isEditing animated:YES];
}

在编辑模式下,左侧会出现圆点标记,可以点击进入编辑模式。

六、批量删除

执行批量删除操作

  1. 批量删除按钮:在 View 中添加一个删除按钮,并通过点击进入编辑模式。
- (IBAction)multipleRemove {
    [self.tableView setEditing:!self.tableView.isEditing animated:YES];
    self.removeButton.hidden = !self.tableView.isEditing;
}

- (IBAction)remove {
    NSMutableArray<XMGWine *> *deletedWineArray = [NSMutableArray array];
    for (NSIndexPath *indexPath in self.tableView.indexPathsForSelectedRows) {
        [deletedWineArray addObject:self.wineArray[indexPath.row]];
    }
    
    [self.wineArray removeObjectsInArray:deletedWineArray];
    [self.tableView deleteRowsAtIndexPaths:self.tableView.indexPathsForSelectedRows withRowAnimation:UITableViewRowAnimationLeft];
}
  1. 初始化:在 viewDidLoad 中设置编辑模式允许多选,并默认隐藏删除按钮。
- (void)viewDidLoad {
    [super viewDidLoad];
    self.tableView.allowsMultipleSelectionDuringEditing = YES;
    self.removeButton.hidden = YES;
}

自定义批量删除

  1. 数据模型:在数据模型中添加 checked 属性,用于标记是否被选中。
@property (nonatomic, assign, getter=isChecked) BOOL checked;
  1. 代理方法:实现 didSelectRowAtIndexPath 方法,用来更新模型的 checked 属性,并刷新对应的 Cell。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    XMGWine *wine = self.wineArray[indexPath.row];
    wine.checked = !wine.isChecked;
    [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
  1. 删除被选中的数据:根据模型的 checked 属性来判断哪些数据需要删除。
- (IBAction)remove {
    NSMutableArray<XMGWine *> *deletedWineArray = [NSMutableArray array];
    for (XMGWine *wine in self.wineArray) {
        if (wine.isChecked) {
            [deletedWineArray addObject:wine];
        }
    }
    [self.wineArray removeObjectsInArray:deletedWineArray];
    [self.tableView reloadData];
}

分析与优化

编辑模式和自定义批量删除为用户提供了更灵活的操作方式。需要注意:

  • 在批量删除时,需要确保删除数据和更新的同步。
  • 自定义批量删除需要根据数据模型进行刷新,以确保数据和视图的一致性。

结论

通过本文的详细解析和具体代码实现,我们了解了如何在 UITableView 中实现全局刷新、局部刷新、左滑操作及批量删除等功能。通过局部刷新可以显著提升表格的性能和用户体验,而左滑操作和批量删除为用户提供了更加灵活的操作方式。

posted @ 2015-07-24 23:00  Mr.陳  阅读(3051)  评论(0编辑  收藏  举报