diff --git a/Source/IGListKit/IGListAdapterUpdater.h b/Source/IGListKit/IGListAdapterUpdater.h index e330abf4..e7e92e15 100644 --- a/Source/IGListKit/IGListAdapterUpdater.h +++ b/Source/IGListKit/IGListAdapterUpdater.h @@ -8,7 +8,9 @@ #import #import -#import +#import +#import +#import NS_ASSUME_NONNULL_BEGIN @@ -22,7 +24,69 @@ NS_ASSUME_NONNULL_BEGIN */ IGLK_SUBCLASSING_RESTRICTED NS_SWIFT_NAME(ListAdapterUpdater) -@interface IGListAdapterUpdater : NSObject +@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; + @end diff --git a/Source/IGListKit/IGListAdapterUpdaterCompatible.h b/Source/IGListKit/IGListAdapterUpdaterCompatible.h deleted file mode 100644 index dc4013d6..00000000 --- a/Source/IGListKit/IGListAdapterUpdaterCompatible.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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 c077f170..695875a5 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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void) listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater willReloadDataWithCollectionView:(UICollectionView *)collectionView isFallbackReload:(BOOL)isFallbackReload; +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater didReloadDataWithCollectionView:(UICollectionView *)collectionView isFallbackReload:(BOOL)isFallbackReload; +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater +- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id)listAdapterUpdater didFinishWithoutUpdatesWithCollectionView:(nullable UICollectionView *)collectionView; +- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater didFinishWithoutUpdatesWithCollectionView:(nullable UICollectionView *)collectionView; @end diff --git a/Source/IGListKit/Internal/IGListBatchUpdateTransaction.h b/Source/IGListKit/Internal/IGListBatchUpdateTransaction.h index e37430a8..181f9337 100644 --- a/Source/IGListKit/Internal/IGListBatchUpdateTransaction.h +++ b/Source/IGListKit/Internal/IGListBatchUpdateTransaction.h @@ -12,7 +12,7 @@ #import "IGListUpdateTransactable.h" -@protocol IGListAdapterUpdaterCompatible; +@class IGListAdapterUpdater; @protocol IGListAdapterUpdaterDelegate; NS_ASSUME_NONNULL_BEGIN @@ -22,7 +22,7 @@ IGLK_SUBCLASSING_RESTRICTED @interface IGListBatchUpdateTransaction : NSObject - (instancetype)initWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock - updater:(id)updater + updater:(IGListAdapterUpdater *)updater delegate:(nullable id)delegate config:(IGListUpdateTransactationConfig)config animated:(BOOL)animated diff --git a/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m b/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m index 1dd13c32..db4fb075 100644 --- a/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m +++ b/Source/IGListKit/Internal/IGListBatchUpdateTransaction.m @@ -29,7 +29,7 @@ typedef NS_ENUM (NSInteger, IGListBatchUpdateTransactionMode) { @interface IGListBatchUpdateTransaction () // Given @property (nonatomic, copy, readonly) UICollectionView *collectionView; -@property (nonatomic, weak, readonly) id updater; +@property (nonatomic, weak, readonly) IGListAdapterUpdater *updater; @property (nonatomic, weak, readonly, nullable) id delegate; @property (nonatomic, assign, readonly) IGListUpdateTransactationConfig config; @property (nonatomic, assign, readonly) BOOL animated; @@ -48,7 +48,7 @@ typedef NS_ENUM (NSInteger, IGListBatchUpdateTransactionMode) { @implementation IGListBatchUpdateTransaction - (instancetype)initWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock - updater:(id)updater + updater:(IGListAdapterUpdater *)updater delegate:(id)delegate config:(IGListUpdateTransactationConfig)config animated:(BOOL)animated diff --git a/Source/IGListKit/Internal/IGListReloadTransaction.h b/Source/IGListKit/Internal/IGListReloadTransaction.h index 182e3ab5..ddaf1f00 100644 --- a/Source/IGListKit/Internal/IGListReloadTransaction.h +++ b/Source/IGListKit/Internal/IGListReloadTransaction.h @@ -12,7 +12,7 @@ #import "IGListUpdateTransactable.h" -@protocol IGListAdapterUpdaterCompatible; +@class IGListAdapterUpdater; @protocol IGListAdapterUpdaterDelegate; NS_ASSUME_NONNULL_BEGIN @@ -22,7 +22,7 @@ IGLK_SUBCLASSING_RESTRICTED @interface IGListReloadTransaction : NSObject - (instancetype)initWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock - updater:(id)updater + updater:(IGListAdapterUpdater *)updater delegate:(nullable id)delegate reloadBlock:(IGListReloadUpdateBlock)reloadBlock itemUpdateBlocks:(NSArray *)itemUpdateBlocks diff --git a/Source/IGListKit/Internal/IGListReloadTransaction.m b/Source/IGListKit/Internal/IGListReloadTransaction.m index 94ce5fff..332e6ddd 100644 --- a/Source/IGListKit/Internal/IGListReloadTransaction.m +++ b/Source/IGListKit/Internal/IGListReloadTransaction.m @@ -12,7 +12,7 @@ @interface IGListReloadTransaction () // Given @property (nonatomic, copy, readonly) UICollectionView *collectionView; -@property (nonatomic, weak, readonly) id updater; +@property (nonatomic, weak, readonly) IGListAdapterUpdater *updater; @property (nonatomic, weak, readonly, nullable) id delegate; @property (nonatomic, copy, readonly) IGListReloadUpdateBlock reloadBlock; @property (nonatomic, copy, readonly) NSArray *itemUpdateBlocks; @@ -25,7 +25,7 @@ @implementation IGListReloadTransaction - (instancetype)initWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock - updater:(id)updater + updater:(IGListAdapterUpdater *)updater delegate:(id)delegate reloadBlock:(IGListReloadUpdateBlock)reloadBlock itemUpdateBlocks:(NSArray *)itemUpdateBlocks diff --git a/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.h b/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.h index 4eb2b55b..e92e9871 100644 --- a/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.h +++ b/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.h @@ -12,7 +12,7 @@ #import "IGListUpdateTransactable.h" -@protocol IGListAdapterUpdaterCompatible; +@class IGListAdapterUpdater; @protocol IGListAdapterUpdaterDelegate; NS_ASSUME_NONNULL_BEGIN @@ -79,7 +79,7 @@ Change the `UICollectionView` dataSource */ - (nullable id)buildWithConfig:(IGListUpdateTransactationConfig)config delegate:(nullable id)delegate - updater:(id)updater; + updater:(IGListAdapterUpdater *)updater; - (BOOL)hasChanges; diff --git a/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.m b/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.m index 39053099..10eabbf0 100644 --- a/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.m +++ b/Source/IGListKit/Internal/IGListUpdateTransactionBuilder.m @@ -140,7 +140,7 @@ typedef NS_ENUM (NSInteger, IGListUpdateTransactionBuilderMode) { - (nullable id)buildWithConfig:(IGListUpdateTransactationConfig)config delegate:(nullable id)delegate - updater:(id)updater { + updater:(IGListAdapterUpdater *)updater { IGListCollectionViewBlock collectionViewBlock = self.collectionViewBlock; if (!collectionViewBlock) { return nil;