From 38877cfc83e16cf2864700c8482440bf66e3d945 Mon Sep 17 00:00:00 2001 From: Maxime Ollivier Date: Tue, 8 Sep 2020 09:06:16 -0700 Subject: [PATCH] protocolize IGListAdapterUpdater Summary: Create temporary protocol for `IGListAdapterUpdater` to test a different implementation. The idea is to ship (or burn) the new implementation before the next 5.0.0 version release. Reviewed By: patters Differential Revision: D23145772 fbshipit-source-id: ede312c4a1289a34f73c14415a9bca40033fe925 --- Source/IGListKit/IGListAdapterUpdater.h | 67 +-------------- Source/IGListKit/IGListAdapterUpdater.m | 8 ++ .../IGListAdapterUpdaterCompatible.h | 86 +++++++++++++++++++ .../IGListKit/IGListAdapterUpdaterDelegate.h | 28 +++--- 4 files changed, 110 insertions(+), 79 deletions(-) create mode 100644 Source/IGListKit/IGListAdapterUpdaterCompatible.h diff --git a/Source/IGListKit/IGListAdapterUpdater.h b/Source/IGListKit/IGListAdapterUpdater.h index 185c535c..e330abf4 100644 --- a/Source/IGListKit/IGListAdapterUpdater.h +++ b/Source/IGListKit/IGListAdapterUpdater.h @@ -7,10 +7,8 @@ #import -#import #import -#import -#import +#import NS_ASSUME_NONNULL_BEGIN @@ -24,68 +22,7 @@ NS_ASSUME_NONNULL_BEGIN */ IGLK_SUBCLASSING_RESTRICTED NS_SWIFT_NAME(ListAdapterUpdater) -@interface IGListAdapterUpdater : NSObject - -/** - The delegate that receives events with data on the performance of a transition. - */ -@property (nonatomic, weak) id delegate; - -/** - A flag indicating if a section move should be treated as a section "delete, then insert" operation. This can be useful if you're - performing a lot of updates and moves are too distracting. - - Default is NO. - */ -@property (nonatomic, assign) BOOL sectionMovesAsDeletesInserts; - -/** - ONLY used when there is N section, but each section only contains 1 item. - We don't need to change move into delete+insert, and we dont need to call -reload at all. - - This unlocks many default UICollectionView animations: move/inline cell updates/deletes/inserts etc. - - Default is NO. - - @warning This should only work for Section that *ONLY* has single item setup. - */ -@property (nonatomic, assign) BOOL singleItemSectionUpdates; - -/** - A flag indicating that section reloads should be treated as item reloads, instead of converting them to "delete, then insert" operations. - This only applies if the number of items for the section is unchanged. - - Default is NO. - - @note If the number of items for the section is changed, we would fallback to the default behavior and convert it to "delete + insert", - because the collectionView can crash otherwise. - */ -@property (nonatomic, assign) BOOL preferItemReloadsForSectionReloads; - -/** - A flag indicating whether this updater should skip diffing and simply call - `reloadData` for updates when the collection view is not in a window. The default value is `YES`. - - Default is YES. - - @note This will result in better performance, but will not generate the same delegate - callbacks. If using a custom layout, it will not receive `prepareForCollectionViewUpdates:`. - - @warning On iOS < 8.3, this behavior is unsupported and will always be treated as `NO`. - */ -@property (nonatomic, assign) BOOL allowsBackgroundReloading; - -/** - If there's more than 100 diff updates, fallback to using `reloadData` to avoid stalling the main thread. - - Default is YES. - */ -@property (nonatomic, assign) BOOL allowsReloadingOnTooManyUpdates; - -/** - A bitmask of experiments to conduct on the updater. - */ -@property (nonatomic, assign) IGListExperiment experiments; +@interface IGListAdapterUpdater : NSObject @end diff --git a/Source/IGListKit/IGListAdapterUpdater.m b/Source/IGListKit/IGListAdapterUpdater.m index 421ab91e..2b94169c 100644 --- a/Source/IGListKit/IGListAdapterUpdater.m +++ b/Source/IGListKit/IGListAdapterUpdater.m @@ -23,6 +23,14 @@ typedef void (^IGListAdapterUpdaterCompletionBlock)(BOOL); @implementation IGListAdapterUpdater +@synthesize delegate = _delegate; +@synthesize sectionMovesAsDeletesInserts = _sectionMovesAsDeletesInserts; +@synthesize singleItemSectionUpdates = _singleItemSectionUpdates; +@synthesize preferItemReloadsForSectionReloads = _preferItemReloadsForSectionReloads; +@synthesize allowsBackgroundReloading = _allowsBackgroundReloading; +@synthesize allowsReloadingOnTooManyUpdates = _allowsReloadingOnTooManyUpdates; +@synthesize experiments = _experiments; + - (instancetype)init { IGAssertMainThread(); diff --git a/Source/IGListKit/IGListAdapterUpdaterCompatible.h b/Source/IGListKit/IGListAdapterUpdaterCompatible.h new file mode 100644 index 00000000..dc4013d6 --- /dev/null +++ b/Source/IGListKit/IGListAdapterUpdaterCompatible.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** +Temporary protocol to test replacing `IGListAdapterUpdater` with `IGListExperimentalAdapterUpdater`. +It extends `IGListUpdatingDelegate` to add more functionaly that might not be needed for all updaters. + */ +NS_SWIFT_NAME(ListAdapterUpdaterCompatible) +@protocol IGListAdapterUpdaterCompatible + +/** + The delegate that receives events with data on the performance of a transition. + */ +@property (nonatomic, weak) id delegate; + +/** + A flag indicating if a section move should be treated as a section "delete, then insert" operation. This can be useful if you're + performing a lot of updates and moves are too distracting. + + Default is NO. + */ +@property (nonatomic, assign) BOOL sectionMovesAsDeletesInserts; + +/** + ONLY used when there is N section, but each section only contains 1 item. + We don't need to change move into delete+insert, and we dont need to call -reload at all. + + This unlocks many default UICollectionView animations: move/inline cell updates/deletes/inserts etc. + + Default is NO. + + @warning This should only work for Section that *ONLY* has single item setup. + */ +@property (nonatomic, assign) BOOL singleItemSectionUpdates; + +/** + A flag indicating that section reloads should be treated as item reloads, instead of converting them to "delete, then insert" operations. + This only applies if the number of items for the section is unchanged. + + Default is NO. + + @note If the number of items for the section is changed, we would fallback to the default behavior and convert it to "delete + insert", + because the collectionView can crash otherwise. + */ +@property (nonatomic, assign) BOOL preferItemReloadsForSectionReloads; + +/** + A flag indicating whether this updater should skip diffing and simply call + `reloadData` for updates when the collection view is not in a window. The default value is `YES`. + + Default is YES. + + @note This will result in better performance, but will not generate the same delegate + callbacks. If using a custom layout, it will not receive `prepareForCollectionViewUpdates:`. + + @warning On iOS < 8.3, this behavior is unsupported and will always be treated as `NO`. + */ +@property (nonatomic, assign) BOOL allowsBackgroundReloading; + +/** + If there's more than 100 diff updates, fallback to using `reloadData` to avoid stalling the main thread. + + Default is YES. + */ +@property (nonatomic, assign) BOOL allowsReloadingOnTooManyUpdates; + +/** + A bitmask of experiments to conduct on the updater. + */ +@property (nonatomic, assign) IGListExperiment experiments; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/IGListKit/IGListAdapterUpdaterDelegate.h b/Source/IGListKit/IGListAdapterUpdaterDelegate.h index 695875a5..c077f170 100644 --- a/Source/IGListKit/IGListAdapterUpdaterDelegate.h +++ b/Source/IGListKit/IGListAdapterUpdaterDelegate.h @@ -9,9 +9,9 @@ #import -@class IGListAdapterUpdater; @class IGListIndexSetResult; @protocol IGListDiffable; +@protocol IGListAdapterUpdaterCompatible; NS_ASSUME_NONNULL_BEGIN @@ -28,7 +28,7 @@ NS_SWIFT_NAME(ListAdapterUpdaterDelegate) @param fromObjects The items transitioned from in the batch updates, if any. @param toObjects The items transitioned to in the batch updates, if any. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater willDiffFromObjects:(nullable NSArray > *)fromObjects toObjects:(nullable NSArray > *)toObjects; @@ -39,7 +39,7 @@ NS_SWIFT_NAME(ListAdapterUpdaterDelegate) @param listIndexSetResults The diffing result of indices to be inserted/removed/updated/moved/etc. @param onBackgroundThread Was the diffing performed on a background thread */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater didDiffWithResults:(nullable IGListIndexSetResult *)listIndexSetResults onBackgroundThread:(BOOL)onBackgroundThread; @@ -53,7 +53,7 @@ NS_SWIFT_NAME(ListAdapterUpdaterDelegate) @param listIndexSetResults The diffing result of indices to be inserted/removed/updated/moved/etc. @param animated Is the cell transtion animated */ -- (void) listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void) listAdapterUpdater:(id)listAdapterUpdater willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView fromObjects:(nullable NSArray > *)fromObjects toObjects:(nullable NSArray > *)toObjects @@ -69,7 +69,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @note This event is called in the completion block of the batch update. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater didPerformBatchUpdates:(IGListBatchUpdateData *)updates collectionView:(UICollectionView *)collectionView; @@ -82,7 +82,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater willInsertIndexPaths:(NSArray *)indexPaths collectionView:(UICollectionView *)collectionView; @@ -95,7 +95,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater willDeleteIndexPaths:(NSArray *)indexPaths collectionView:(UICollectionView *)collectionView; @@ -109,7 +109,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater willMoveFromIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath collectionView:(UICollectionView *)collectionView; @@ -123,7 +123,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater willReloadIndexPaths:(NSArray *)indexPaths collectionView:(UICollectionView *)collectionView; @@ -136,7 +136,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @note This event is only sent when outside of `-[UICollectionView performBatchUpdates:completion:]`. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater willReloadSections:(NSIndexSet *)sections collectionView:(UICollectionView *)collectionView; @@ -147,7 +147,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @param collectionView The collection view that will be reloaded. @param isFallbackReload The reload was a fallback because we could not performBatchUpdate */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater willReloadDataWithCollectionView:(UICollectionView *)collectionView isFallbackReload:(BOOL)isFallbackReload; +- (void)listAdapterUpdater:(id)listAdapterUpdater willReloadDataWithCollectionView:(UICollectionView *)collectionView isFallbackReload:(BOOL)isFallbackReload; /** Notifies the delegate that the updater successfully called `-[UICollectionView reloadData]`. @@ -156,7 +156,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @param collectionView The collection view that reloaded. @param isFallbackReload The reload was a fallback because we could not performBatchUpdate */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater didReloadDataWithCollectionView:(UICollectionView *)collectionView isFallbackReload:(BOOL)isFallbackReload; +- (void)listAdapterUpdater:(id)listAdapterUpdater didReloadDataWithCollectionView:(UICollectionView *)collectionView isFallbackReload:(BOOL)isFallbackReload; /** Notifies the delegate that the collection view threw an exception in `-[UICollectionView performBatchUpdates:completion:]`. @@ -169,7 +169,7 @@ willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView @param diffResult The diff result that were computed from `fromObjects` and `toObjects`. @param updates The batch updates that were applied to the collection view. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater +- (void)listAdapterUpdater:(id)listAdapterUpdater collectionView:(UICollectionView *)collectionView willCrashWithException:(NSException *)exception fromObjects:(nullable NSArray *)fromObjects @@ -183,7 +183,7 @@ Notifies the delegate that the updater finished without performing any batch upd @param listAdapterUpdater The adapter updater owning the transition. @param collectionView The collection view that reloaded. */ -- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater didFinishWithoutUpdatesWithCollectionView:(nullable UICollectionView *)collectionView; +- (void)listAdapterUpdater:(id)listAdapterUpdater didFinishWithoutUpdatesWithCollectionView:(nullable UICollectionView *)collectionView; @end