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
This commit is contained in:
Maxime Ollivier 2020-09-08 09:06:16 -07:00 committed by Facebook GitHub Bot
parent aca18c7470
commit 38877cfc83
4 changed files with 110 additions and 79 deletions

View file

@ -7,10 +7,8 @@
#import <UIKit/UIKit.h>
#import <IGListDiffKit/IGListExperiments.h>
#import <IGListDiffKit/IGListMacros.h>
#import <IGListKit/IGListAdapterUpdaterDelegate.h>
#import <IGListKit/IGListUpdatingDelegate.h>
#import <IGListKit/IGListAdapterUpdaterCompatible.h>
NS_ASSUME_NONNULL_BEGIN
@ -24,68 +22,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
IGLK_SUBCLASSING_RESTRICTED
NS_SWIFT_NAME(ListAdapterUpdater)
@interface IGListAdapterUpdater : NSObject <IGListUpdatingDelegate>
/**
The delegate that receives events with data on the performance of a transition.
*/
@property (nonatomic, weak) id<IGListAdapterUpdaterDelegate> 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 <IGListAdapterUpdaterCompatible>
@end

View file

@ -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();

View file

@ -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 <Foundation/Foundation.h>
#import <IGListKit/IGListUpdatingDelegate.h>
#import <IGListDiffKit/IGListExperiments.h>
#import <IGListKit/IGListAdapterUpdaterDelegate.h>
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 <IGListUpdatingDelegate>
/**
The delegate that receives events with data on the performance of a transition.
*/
@property (nonatomic, weak) id<IGListAdapterUpdaterDelegate> 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

View file

@ -9,9 +9,9 @@
#import <IGListDiffKit/IGListBatchUpdateData.h>
@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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
willDiffFromObjects:(nullable NSArray <id<IGListDiffable>> *)fromObjects
toObjects:(nullable NSArray <id<IGListDiffable>> *)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
willPerformBatchUpdatesWithCollectionView:(UICollectionView *)collectionView
fromObjects:(nullable NSArray <id<IGListDiffable>> *)fromObjects
toObjects:(nullable NSArray <id<IGListDiffable>> *)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
willInsertIndexPaths:(NSArray<NSIndexPath *> *)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
willDeleteIndexPaths:(NSArray<NSIndexPath *> *)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
willReloadIndexPaths:(NSArray<NSIndexPath *> *)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater didFinishWithoutUpdatesWithCollectionView:(nullable UICollectionView *)collectionView;
@end