iOS开发基础20-UITableView的全局及局部刷新、左滑操作与批量删除
UITableView
是 iOS 开发中广泛使用的组件,用于展示大量数据项。对于更好的用户体验,通常需要支持数据的动态更新、左滑操作和批量删除功能。本篇文章将详细介绍如何实现这些功能,并对背后的一些底层逻辑进行深入分析。
前期准备
项目初始化
- 创建项目:打开 Xcode,创建一个新的 iOS 项目。
- 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];
}
在编辑模式下,左侧会出现圆点标记,可以点击进入编辑模式。
六、批量删除
执行批量删除操作
- 批量删除按钮:在 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];
}
- 初始化:在
viewDidLoad
中设置编辑模式允许多选,并默认隐藏删除按钮。
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.allowsMultipleSelectionDuringEditing = YES;
self.removeButton.hidden = YES;
}
自定义批量删除
- 数据模型:在数据模型中添加
checked
属性,用于标记是否被选中。
@property (nonatomic, assign, getter=isChecked) BOOL checked;
- 代理方法:实现
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];
}
- 删除被选中的数据:根据模型的
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
中实现全局刷新、局部刷新、左滑操作及批量删除等功能。通过局部刷新可以显著提升表格的性能和用户体验,而左滑操作和批量删除为用户提供了更加灵活的操作方式。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!