2019-12-19 17:32:49 +00:00
|
|
|
/*
|
2023-04-06 09:44:16 +00:00
|
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
2016-09-07 22:37:59 +00:00
|
|
|
*
|
2019-12-19 17:32:49 +00:00
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
2016-09-07 22:37:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#import "IGListTestUICollectionViewDataSource.h"
|
|
|
|
|
|
2019-12-17 21:05:00 +00:00
|
|
|
#import <IGListDiffKit/IGListAssert.h>
|
2019-12-04 23:30:33 +00:00
|
|
|
|
Add option to update cells instead of delete+insert for section reload
Summary:
We have seen unnecessary flashiness updates for any section reload updates.
Basically we have 1 section for 1 cell, which is recommended by the IGListKit document in https://instagram.github.io/IGListKit/best-practices-and-faq.html, specifically:
> "We highly recommend using single-item sections when possible."
However, the issue is that whenever we update the underlying data model, we would trigger a delete+insert for the section reload.
In order to mitigate that, we can fix this delete+insert changes or we use the `IGListBindingSectionController`, however, the latter one requires more refactoring plus view model wrapper to have `isEqualToDifferable:` to return YES, which seems less than ideal.
I am proposing that we add an option to the `IGListAdapterUpdater`, as `preferItemReloadsForSectionReloads` so that when it's set to YES, we would trigger the proper `-[UICollectionView reloadItemsAtIndexPaths:]` which handles the cell update properly.
This option also handles the case where the number of items in the section is changed before and after the updates, in that case, it will fallback to do the "delete+insert" section operation.
Reviewed By: rnystrom
Differential Revision: D9519519
fbshipit-source-id: 22ecca07679ebdd212cf771c61e40887cb6a9ba8
2018-08-29 06:22:13 +00:00
|
|
|
@implementation IGSectionObject {
|
|
|
|
|
NSString *_identifier;
|
2019-12-04 23:30:33 +00:00
|
|
|
BOOL _usesIdentifierForDiffable;
|
Add option to update cells instead of delete+insert for section reload
Summary:
We have seen unnecessary flashiness updates for any section reload updates.
Basically we have 1 section for 1 cell, which is recommended by the IGListKit document in https://instagram.github.io/IGListKit/best-practices-and-faq.html, specifically:
> "We highly recommend using single-item sections when possible."
However, the issue is that whenever we update the underlying data model, we would trigger a delete+insert for the section reload.
In order to mitigate that, we can fix this delete+insert changes or we use the `IGListBindingSectionController`, however, the latter one requires more refactoring plus view model wrapper to have `isEqualToDifferable:` to return YES, which seems less than ideal.
I am proposing that we add an option to the `IGListAdapterUpdater`, as `preferItemReloadsForSectionReloads` so that when it's set to YES, we would trigger the proper `-[UICollectionView reloadItemsAtIndexPaths:]` which handles the cell update properly.
This option also handles the case where the number of items in the section is changed before and after the updates, in that case, it will fallback to do the "delete+insert" section operation.
Reviewed By: rnystrom
Differential Revision: D9519519
fbshipit-source-id: 22ecca07679ebdd212cf771c61e40887cb6a9ba8
2018-08-29 06:22:13 +00:00
|
|
|
}
|
2016-09-07 22:37:59 +00:00
|
|
|
|
|
|
|
|
+ (instancetype)sectionWithObjects:(NSArray *)objects {
|
2019-12-04 23:30:33 +00:00
|
|
|
return [IGSectionObject sectionWithObjects:objects identifier:[NSUUID UUID].UUIDString usesIdentifierForDiffable:NO];
|
Add option to update cells instead of delete+insert for section reload
Summary:
We have seen unnecessary flashiness updates for any section reload updates.
Basically we have 1 section for 1 cell, which is recommended by the IGListKit document in https://instagram.github.io/IGListKit/best-practices-and-faq.html, specifically:
> "We highly recommend using single-item sections when possible."
However, the issue is that whenever we update the underlying data model, we would trigger a delete+insert for the section reload.
In order to mitigate that, we can fix this delete+insert changes or we use the `IGListBindingSectionController`, however, the latter one requires more refactoring plus view model wrapper to have `isEqualToDifferable:` to return YES, which seems less than ideal.
I am proposing that we add an option to the `IGListAdapterUpdater`, as `preferItemReloadsForSectionReloads` so that when it's set to YES, we would trigger the proper `-[UICollectionView reloadItemsAtIndexPaths:]` which handles the cell update properly.
This option also handles the case where the number of items in the section is changed before and after the updates, in that case, it will fallback to do the "delete+insert" section operation.
Reviewed By: rnystrom
Differential Revision: D9519519
fbshipit-source-id: 22ecca07679ebdd212cf771c61e40887cb6a9ba8
2018-08-29 06:22:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (instancetype)sectionWithObjects:(NSArray *)objects identifier:(NSString *)identifier {
|
2019-12-04 23:30:33 +00:00
|
|
|
return [IGSectionObject sectionWithObjects:objects identifier:identifier usesIdentifierForDiffable:NO];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (instancetype)sectionWithObjects:(NSArray *)objects identifier:(NSString *)identifier usesIdentifierForDiffable:(BOOL)usesIdentifierForDiffable {
|
2016-09-07 22:37:59 +00:00
|
|
|
IGSectionObject *object = [[IGSectionObject alloc] init];
|
|
|
|
|
object.objects = objects;
|
Add option to update cells instead of delete+insert for section reload
Summary:
We have seen unnecessary flashiness updates for any section reload updates.
Basically we have 1 section for 1 cell, which is recommended by the IGListKit document in https://instagram.github.io/IGListKit/best-practices-and-faq.html, specifically:
> "We highly recommend using single-item sections when possible."
However, the issue is that whenever we update the underlying data model, we would trigger a delete+insert for the section reload.
In order to mitigate that, we can fix this delete+insert changes or we use the `IGListBindingSectionController`, however, the latter one requires more refactoring plus view model wrapper to have `isEqualToDifferable:` to return YES, which seems less than ideal.
I am proposing that we add an option to the `IGListAdapterUpdater`, as `preferItemReloadsForSectionReloads` so that when it's set to YES, we would trigger the proper `-[UICollectionView reloadItemsAtIndexPaths:]` which handles the cell update properly.
This option also handles the case where the number of items in the section is changed before and after the updates, in that case, it will fallback to do the "delete+insert" section operation.
Reviewed By: rnystrom
Differential Revision: D9519519
fbshipit-source-id: 22ecca07679ebdd212cf771c61e40887cb6a9ba8
2018-08-29 06:22:13 +00:00
|
|
|
object->_identifier = [identifier copy];
|
2019-12-04 23:30:33 +00:00
|
|
|
object->_usesIdentifierForDiffable = usesIdentifierForDiffable;
|
2016-09-07 22:37:59 +00:00
|
|
|
return object;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#pragma mark - IGListDiffable
|
|
|
|
|
|
|
|
|
|
- (id<NSObject>)diffIdentifier {
|
Add option to update cells instead of delete+insert for section reload
Summary:
We have seen unnecessary flashiness updates for any section reload updates.
Basically we have 1 section for 1 cell, which is recommended by the IGListKit document in https://instagram.github.io/IGListKit/best-practices-and-faq.html, specifically:
> "We highly recommend using single-item sections when possible."
However, the issue is that whenever we update the underlying data model, we would trigger a delete+insert for the section reload.
In order to mitigate that, we can fix this delete+insert changes or we use the `IGListBindingSectionController`, however, the latter one requires more refactoring plus view model wrapper to have `isEqualToDifferable:` to return YES, which seems less than ideal.
I am proposing that we add an option to the `IGListAdapterUpdater`, as `preferItemReloadsForSectionReloads` so that when it's set to YES, we would trigger the proper `-[UICollectionView reloadItemsAtIndexPaths:]` which handles the cell update properly.
This option also handles the case where the number of items in the section is changed before and after the updates, in that case, it will fallback to do the "delete+insert" section operation.
Reviewed By: rnystrom
Differential Revision: D9519519
fbshipit-source-id: 22ecca07679ebdd212cf771c61e40887cb6a9ba8
2018-08-29 06:22:13 +00:00
|
|
|
return _identifier;
|
2016-09-07 22:37:59 +00:00
|
|
|
}
|
|
|
|
|
|
2016-11-11 00:55:33 +00:00
|
|
|
- (BOOL)isEqualToDiffableObject:(id)object {
|
2016-09-07 22:37:59 +00:00
|
|
|
if (object == self) {
|
|
|
|
|
return YES;
|
|
|
|
|
} else if ([object isKindOfClass:IGSectionObject.class]) {
|
2019-12-04 23:30:33 +00:00
|
|
|
IGSectionObject *sectionObject = (IGSectionObject *)object;
|
|
|
|
|
if (_usesIdentifierForDiffable) {
|
|
|
|
|
return [_identifier isEqualToString:sectionObject->_identifier];
|
|
|
|
|
} else {
|
|
|
|
|
return [self isEqual:object];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (BOOL)isEqual:(id)object {
|
|
|
|
|
if (object == self) {
|
|
|
|
|
return YES;
|
|
|
|
|
} else if ([object isKindOfClass:IGSectionObject.class]) {
|
|
|
|
|
IGSectionObject *sectionObject = (IGSectionObject *)object;
|
|
|
|
|
return ([self.objects isEqualToArray:sectionObject.objects]
|
|
|
|
|
&& [_identifier isEqualToString:sectionObject->_identifier]);
|
2016-09-07 22:37:59 +00:00
|
|
|
} else {
|
|
|
|
|
return NO;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation IGListTestUICollectionViewDataSource
|
|
|
|
|
|
|
|
|
|
- (instancetype)initWithCollectionView:(UICollectionView *)collectionView {
|
|
|
|
|
if (self = [super init]) {
|
|
|
|
|
collectionView.dataSource = self;
|
|
|
|
|
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
|
|
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
|
|
|
|
|
return self.sections.count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
|
|
|
|
|
return [[self.sections[section] objects] count];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
|
|
|
|
|
return cell;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@end
|