Skip to content

Instantly share code, notes, and snippets.

@jwamin
Last active September 12, 2021 18:09
Show Gist options
  • Save jwamin/01037a456bf3b0bd26ecd8fe62eb931b to your computer and use it in GitHub Desktop.
Save jwamin/01037a456bf3b0bd26ecd8fe62eb931b to your computer and use it in GitHub Desktop.
Diffable Datasource with Updating Cells - Objective-C
//
// ViewController.m
// UpdatingCells
//
// Created by Joss Manger on 9/6/21.
//
#import "ViewController.h"
typedef NS_ENUM(NSInteger, JSYSectionType){
JSYSectionTypeFirstSection
};
@protocol SectionDataProtocol <NSObject>
@property (readonly) NSString* sectionTitle;
@property (readonly) JSYSectionType sectionType;
@end
@interface JSYSection : NSObject <SectionDataProtocol>{
NSString* sectionTitle;
JSYSectionType sectionType;
}
- (instancetype)initNewSection:(NSString *)title and:(JSYSectionType)type;
@end
@implementation JSYSection
@synthesize sectionTitle;
@synthesize sectionType;
- (instancetype)initNewSection:(NSString *)title and:(JSYSectionType)type{
self = [super init];
if (self){
sectionTitle = [[NSString alloc] initWithString:title];
sectionType = type;
}
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"it's a Section!\n title: %@ type:%ld", sectionTitle, (long)sectionType];
}
@end
@protocol CellDataProtocol <NSObject>
@property BOOL animating;
@property NSString* titleString;
@end
@interface CellData : NSObject <CellDataProtocol>
@property BOOL animating;
@property NSString* titleString;
- (instancetype)initWithString:(NSString*)title withAnimationState:(BOOL)animation;
@end
@implementation CellData
- (instancetype)initWithString:(NSString*)title withAnimationState:(BOOL)animation
{
self = [super init];
if (self) {
_animating = animation;
_titleString = title;
}
return self;
}
@end
@interface JSSYUpdatingCell : UITableViewCell
- (void)setUpdating:(BOOL)updating;
- (void)toggleUpdating:(id<CellDataProtocol>)data;
+(NSString*)identifier;
@end
@implementation JSSYUpdatingCell{
UIActivityIndicatorView *indicator;
BOOL isUpdating;
}
+ (NSString *)identifier{
return @"jssyCell";
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
isUpdating = NO;
indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
[self.contentView addSubview:indicator];
}
return self;
}
- (void)setUpdating:(BOOL)updating{
updating ? [indicator startAnimating] : [indicator stopAnimating];
__weak JSSYUpdatingCell *weakCell = self;
[UIView animateWithDuration:1 animations:^{
JSSYUpdatingCell *strSelf = weakCell;
CGRect frame = strSelf->indicator.frame;
if (updating) {
[strSelf->indicator setCenter:[[strSelf contentView] center]];
} else {
[strSelf->indicator setFrame:CGRectMake(0, 0, CGRectGetWidth(frame), CGRectGetHeight(frame))];
}
[strSelf.contentView setNeedsLayout];
[strSelf.contentView layoutIfNeeded];
}];
NSLog(@"is updating %@",(isUpdating ? @"YES" : @"NO"));
}
- (void)toggleUpdating:(id<CellDataProtocol>)data {
[self setUpdating:data.animating];
}
@end
@interface MyDiffableDataSource : UITableViewDiffableDataSource
@end
@implementation MyDiffableDataSource
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
JSYSection *sectionModel = [[self snapshot] sectionIdentifiers][section];
return [sectionModel sectionTitle];
}
@end
@interface ViewController ()
@end
@implementation ViewController {
UITableView *tableView;
UITableViewDiffableDataSource *dataSource;
}
- (void)viewDidLoad {
[super viewDidLoad];
tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
[tableView setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
[tableView registerClass:[JSSYUpdatingCell class] forCellReuseIdentifier:[JSSYUpdatingCell identifier]];
[self.view addSubview:tableView];
UITableViewDiffableDataSourceCellProvider provider = ^UITableViewCell * _Nullable(UITableView *tableView, NSIndexPath *path, id something) {
JSSYUpdatingCell *cell = [tableView dequeueReusableCellWithIdentifier:[JSSYUpdatingCell identifier]];
CellData* cellData = (CellData*)something;
[cell.textLabel setText:cellData.titleString];
return cell;
};
dataSource = [[MyDiffableDataSource alloc] initWithTableView:tableView cellProvider: provider];
[tableView setDataSource:dataSource];
__weak id<UITableViewDelegate> delegate = (id<UITableViewDelegate>)self;
[tableView setDelegate:delegate];
NSDiffableDataSourceSnapshot *snapshot = [dataSource snapshot];
JSYSection *section = [[JSYSection alloc] initNewSection:@"SECTION!" and:JSYSectionTypeFirstSection];
[snapshot appendSectionsWithIdentifiers:@[section]];
[snapshot appendItemsWithIdentifiers:@[
[[CellData alloc] initWithString:@"Hello" withAnimationState:YES],
[[CellData alloc] initWithString:@"World" withAnimationState:NO],
[[CellData alloc] initWithString:@"Jossy" withAnimationState:NO]
]];
__weak ViewController *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
ViewController *strongSelf = weakSelf;
[strongSelf->dataSource applySnapshot:snapshot animatingDifferences:YES];
});
// Do any additional setup after loading the view.
}
@end
@interface ViewController (ViewControllerConformingToDelegate) <UITableViewDelegate>
@end
@implementation ViewController (ViewControllerConformingToDelegate)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSLog(@"oh hello %@",indexPath);
JSSYUpdatingCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CellData* cellData = [dataSource itemIdentifierForIndexPath:indexPath];
[cellData setAnimating:!cellData.animating];
[cell toggleUpdating:cellData];
}
@end
@jwamin
Copy link
Author

jwamin commented Sep 12, 2021

added custom cell type with readonly properties

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment