前言:
UITableViewDiffableDataSource仅支持iOS 13以上系统调用,如果用在实际项目开发中请注意一下。个人建议还是使用UITableViewDataSource为好。
UITableViewDiffableDataSource继承自NSObject,我们使用时一般创建一个继承自它的新类,例如MYTableViewDiffableDataSource。在这个类中你可以实现UITableViewDataSource的一些代理方法,以便扩展更多的功能。
简单API介绍:
1、调用appendSectionsWithIdentifiers添加section:
- (void)appendSectionsWithIdentifiers:(NSArray*)sectionIdentifiers;
2、调用appendItemsWithIdentifiers在最后一个section中添加item数据:
- (void)appendItemsWithIdentifiers:(NSArray<ItemIdentifierType>*)identifiers;
3、在指定的section中添加item数据:
- (void)appendItemsWithIdentifiers:(NSArray<ItemIdentifierType>*)identifiers intoSectionWithIdentifier:(SectionIdentifierType)sectionIdentifier
4、删除指定的item数据:
- (void)deleteItemsWithIdentifiers:(NSArray<ItemIdentifierType>*)identifiers;
5、删除所有数据:
- (void)deleteAllItems;
………………太多了,这里省略,接下来是关键……
n、将以上改动(添加、删除、移动……)应用到tableview中:
- (void)applySnapshot:(NSDiffableDataSourceSnapshot<SectionIdentifierType,ItemIdentifierType>*)snapshot animatingDifferences:(BOOL)animatingDifferences;
话不多说,上代码!完整demo项目地址在文章末尾
效果图:
demo代码:(注释很重要)
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "MYTableViewDiffableDataSource.h"
@interface MasterViewController ()
@property NSMutableArray *objects;
@property (nonatomic) MYTableViewDiffableDataSource *datasource; //创建自己的类以便实现更多的UITableViewDataSource代理方法
@end
@implementation MasterViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
//指定新的代理
self.tableView.dataSource = self.datasource;
}
- (UITableViewDiffableDataSource *)datasource {
if (!_datasource) {
_datasource = [[MYTableViewDiffableDataSource alloc] initWithTableView:self.tableView cellProvider:^UITableViewCell * _Nullable(UITableView * _Nonnull tableView, NSIndexPath * _Nonnull indexPath, id _Nonnull date) {
//
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
NSDate *object = date;
cell.textLabel.text = [object description];
return cell;
}];
}
return _datasource;
}
- (void)viewWillAppear:(BOOL)animated {
self.clearsSelectionOnViewWillAppear = self.splitViewController.isCollapsed;
[super viewWillAppear:animated];
}
- (void)insertNewObject:(id)sender {
NSDiffableDataSourceSnapshot *snapshot = self.datasource.snapshot;
//不可以每次都创建新的snapshot⚠️,否则数据都是新的!
//NSDiffableDataSourceSnapshot *snapshot = [[NSDiffableDataSourceSnapshot alloc] init];
//数据太多了清空一下
if (snapshot.numberOfItems >= 10) {
[snapshot deleteAllItems];
[self.datasource applySnapshot:snapshot animatingDifferences:YES completion:^{
}];
return;
}
//必须先创建Section才可以插入数据
if(snapshot.numberOfSections==0)
{
[snapshot appendSectionsWithIdentifiers:@[@"1"]]; //SectionIdentifierType不可以重复⚠️
}else
{
if (snapshot.numberOfItems == 5) {
[snapshot appendSectionsWithIdentifiers:@[@"2"]]; //根据需求添加更多的Section
}
}
//往Section中添加数据,默认添加到最后一个Section中
[snapshot appendItemsWithIdentifiers:@[[NSDate date]]]; //ItemIdentifierType也不可以重复⚠️
//往指定Section中添加数据
//[snapshot appendItemsWithIdentifiers:@[[NSDate date]] intoSectionWithIdentifier:@"2"];
[self.datasource applySnapshot:snapshot animatingDifferences:YES completion:^{
//
}];
}
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDate *object = [self.datasource itemIdentifierForIndexPath:indexPath];
DetailViewController *controller = (DetailViewController *)[[segue destinationViewController] topViewController];
controller.detailItem = object;
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
controller.navigationItem.leftItemsSupplementBackButton = YES;
self.detailViewController = controller;
}
}
//⚠️不可以再实现以下方法⚠️
//#pragma mark - Table View
//
//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// return 1;
//}
//
//
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// return self.objects.count;
//}
//
//
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
//
// NSDate *object = self.objects[indexPath.row];
// cell.textLabel.text = [object description];
// return cell;
//}
@end
@interface MYTableViewDiffableDataSource : UITableViewDiffableDataSource
@end
#import "MYTableViewDiffableDataSource.h"
@implementation MYTableViewDiffableDataSource
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
id item = [self itemIdentifierForIndexPath:indexPath];
//这里注意一下,每次调用self.snapshot都会创建新的对象⚠️⚠️⚠️
NSDiffableDataSourceSnapshot *snapshot = self.snapshot;
NSDiffableDataSourceSnapshot *snapshot1 = self.snapshot; //测试⚠️
NSDiffableDataSourceSnapshot *snapshot2 = self.snapshot; //测试⚠️
NSDiffableDataSourceSnapshot *snapshot3 = self.snapshot; //测试⚠️
//删除的时候不用指定Section,因为每一个item都是唯一的
[snapshot deleteItemsWithIdentifiers:@[item]];
[self applySnapshot:snapshot animatingDifferences:YES completion:^{
//
}];
//不可以再使用tableview的方法删除⚠️⚠️⚠️
//[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 20;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%ld",section];
}
@end
项目地址:GitHub