From 219b659b38724f1d56d1184fc68be17e68970c17 Mon Sep 17 00:00:00 2001 From: Huy Nguyen Date: Sat, 8 Aug 2015 20:54:07 +0300 Subject: [PATCH] - Automatically relayout cells when editing mode is used. - Add editing mode to Kitten sample. --- AsyncDisplayKit/ASTableView.mm | 36 ++++++++++++++++++++- examples/Kittens/Sample/AppDelegate.m | 2 +- examples/Kittens/Sample/ViewController.m | 41 ++++++++++++++++++++---- 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/AsyncDisplayKit/ASTableView.mm b/AsyncDisplayKit/ASTableView.mm index c32a585a72..f605a10a6b 100644 --- a/AsyncDisplayKit/ASTableView.mm +++ b/AsyncDisplayKit/ASTableView.mm @@ -104,18 +104,31 @@ static BOOL _isInterceptedSelector(SEL sel) #pragma mark - #pragma mark ASCellNode<->UITableViewCell bridging. +@protocol _ASTableViewCellDelegate +- (void)tableViewCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath didTransitionToState:(UITableViewCellStateMask)state; +@end + @interface _ASTableViewCell : UITableViewCell +@property (nonatomic, weak) id<_ASTableViewCellDelegate> delegate; +@property (nonatomic) NSIndexPath *indexPath; @end @implementation _ASTableViewCell // TODO add assertions to prevent use of view-backed UITableViewCell properties (eg .textLabel) + +- (void)didTransitionToState:(UITableViewCellStateMask)state +{ + [super didTransitionToState:state]; + [_delegate tableViewCell:self atIndexPath:_indexPath didTransitionToState:state]; +} + @end #pragma mark - #pragma mark ASTableView -@interface ASTableView () { +@interface ASTableView () { _ASTableViewProxy *_proxyDataSource; _ASTableViewProxy *_proxyDelegate; @@ -493,11 +506,13 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { _ASTableViewCell *cell = [self dequeueReusableCellWithIdentifier:reuseIdentifier]; if (!cell) { cell = [[_ASTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier]; + cell.delegate = self; } ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; [_rangeController configureContentView:cell.contentView forCellNode:node]; + cell.indexPath = indexPath; cell.backgroundColor = node.backgroundColor; cell.selectionStyle = node.selectionStyle; @@ -827,4 +842,23 @@ void ASPerformBlockWithoutAnimation(BOOL withoutAnimation, void (^block)()) { } } +#pragma mark - _ASTableViewCellDelegate + +- (void)tableViewCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath didTransitionToState:(UITableViewCellStateMask)state +{ + [self beginUpdates]; + ASCellNode *node = [_dataController nodeAtIndexPath:indexPath]; + + CGSize constrainedSize = [self dataController:_dataController constrainedSizeForNodeAtIndexPath:indexPath]; + if (state != UITableViewCellStateDefaultMask) { + // Edit control or delete confirmation was shown and size of content view was changed. + // The new size should be taken into consideration. + constrainedSize.width = MIN(cell.contentView.frame.size.width, constrainedSize.width); + } + + [node measure:constrainedSize]; + node.frame = CGRectMake(0, 0, node.calculatedSize.width, node.calculatedSize.height); + [self endUpdates]; +} + @end diff --git a/examples/Kittens/Sample/AppDelegate.m b/examples/Kittens/Sample/AppDelegate.m index a8e5594780..1dea563b77 100644 --- a/examples/Kittens/Sample/AppDelegate.m +++ b/examples/Kittens/Sample/AppDelegate.m @@ -19,7 +19,7 @@ { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.backgroundColor = [UIColor whiteColor]; - self.window.rootViewController = [[ViewController alloc] init]; + self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]]; [self.window makeKeyAndVisible]; return YES; } diff --git a/examples/Kittens/Sample/ViewController.m b/examples/Kittens/Sample/ViewController.m index 12e5123079..02760a6355 100644 --- a/examples/Kittens/Sample/ViewController.m +++ b/examples/Kittens/Sample/ViewController.m @@ -27,12 +27,13 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell ASTableView *_tableView; // array of boxed CGSizes corresponding to placekitten.com kittens - NSArray *_kittenDataSource; + NSMutableArray *_kittenDataSource; BOOL _dataSourceLocked; + NSIndexPath *_blurbNodeIndexPath; } -@property (nonatomic, strong) NSArray *kittenDataSource; +@property (nonatomic, strong) NSMutableArray *kittenDataSource; @property (atomic, assign) BOOL dataSourceLocked; @end @@ -56,10 +57,16 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell // populate our "data source" with some random kittens _kittenDataSource = [self createLitterWithSize:kLitterSize]; + _blurbNodeIndexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit + target:self + action:@selector(toggleEditingMode)]; + return self; } -- (NSArray *)createLitterWithSize:(NSInteger)litterSize +- (NSMutableArray *)createLitterWithSize:(NSInteger)litterSize { NSMutableArray *kittens = [NSMutableArray arrayWithCapacity:litterSize]; for (NSInteger i = 0; i < litterSize; i++) { @@ -75,7 +82,7 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell return kittens; } -- (void)setKittenDataSource:(NSArray *)kittenDataSource { +- (void)setKittenDataSource:(NSMutableArray *)kittenDataSource { ASDisplayNodeAssert(!self.dataSourceLocked, @"Could not update data source when it is locked !"); _kittenDataSource = kittenDataSource; @@ -98,6 +105,11 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell return YES; } +- (void)toggleEditingMode +{ + [_tableView setEditing:!_tableView.editing animated:YES]; +} + #pragma mark - #pragma mark ASTableView. @@ -115,7 +127,7 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell - (ASCellNode *)tableView:(ASTableView *)tableView nodeForRowAtIndexPath:(NSIndexPath *)indexPath { // special-case the first row - if (indexPath.section == 0 && indexPath.row == 0) { + if ([_blurbNodeIndexPath compare:indexPath] == NSOrderedSame) { BlurbNode *node = [[BlurbNode alloc] init]; return node; } @@ -134,7 +146,7 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell - (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath { // Enable selection for kitten nodes - return indexPath.section != 0 || indexPath.row != 0; + return [_blurbNodeIndexPath compare:indexPath] != NSOrderedSame; } - (void)tableViewLockDataSource:(ASTableView *)tableView @@ -173,7 +185,7 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell } // add new kittens to the data source & notify table of new indexpaths - _kittenDataSource = [_kittenDataSource arrayByAddingObjectsFromArray:moarKittens]; + [_kittenDataSource addObjectsFromArray:moarKittens]; [tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; [context completeBatchFetching:YES]; @@ -183,4 +195,19 @@ static const NSInteger kMaxLitterSize = 100; // max number of kitten cell }); } +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath +{ + // Enable editing for Kitten nodes + return [_blurbNodeIndexPath compare:indexPath] != NSOrderedSame; +} + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (editingStyle == UITableViewCellEditingStyleDelete) { + // Assume only kitten nodes are editable (see -tableView:canEditRowAtIndexPath:). + [_kittenDataSource removeObjectAtIndex:indexPath.row - 1]; + [_tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + } +} + @end