mirror of
https://github.com/Instagram/IGListKit
synced 2026-05-23 01:08:27 +00:00
remove protocol IGListAdapterUpdaterCompatible
Summary: Now that the experimental updater is done, we can remove this protocol. Reviewed By: iperry90 Differential Revision: D25884776 fbshipit-source-id: e7ce962f166aecf73ca1e8fdfa41404bc794696e
This commit is contained in:
parent
9994d5abc2
commit
6c48800ff5
9 changed files with 91 additions and 113 deletions
|
|
@ -8,7 +8,9 @@
|
|||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import <IGListDiffKit/IGListMacros.h>
|
||||
#import <IGListKit/IGListAdapterUpdaterCompatible.h>
|
||||
#import <IGListKit/IGListUpdatingDelegate.h>
|
||||
#import <IGListDiffKit/IGListExperiments.h>
|
||||
#import <IGListKit/IGListAdapterUpdaterDelegate.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
|
|
@ -22,7 +24,69 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
*/
|
||||
IGLK_SUBCLASSING_RESTRICTED
|
||||
NS_SWIFT_NAME(ListAdapterUpdater)
|
||||
@interface IGListAdapterUpdater : NSObject <IGListAdapterUpdaterCompatible>
|
||||
@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;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <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
|
||||
|
|
@ -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:(id<IGListAdapterUpdaterCompatible>)listAdapterUpdater
|
||||
- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
|
||||
- (void) listAdapterUpdater:(IGListAdapterUpdater *)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:(id<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
|
||||
- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id<IGListAdapterUpdaterCompatible>)listAdapterUpdater
|
||||
- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater
|
||||
- (void)listAdapterUpdater:(IGListAdapterUpdater *)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:(id<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)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<IGListAdapterUpdaterCompatible>)listAdapterUpdater didFinishWithoutUpdatesWithCollectionView:(nullable UICollectionView *)collectionView;
|
||||
- (void)listAdapterUpdater:(IGListAdapterUpdater *)listAdapterUpdater didFinishWithoutUpdatesWithCollectionView:(nullable UICollectionView *)collectionView;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <IGListUpdateTransactable>
|
||||
|
||||
- (instancetype)initWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock
|
||||
updater:(id<IGListAdapterUpdaterCompatible>)updater
|
||||
updater:(IGListAdapterUpdater *)updater
|
||||
delegate:(nullable id<IGListAdapterUpdaterDelegate>)delegate
|
||||
config:(IGListUpdateTransactationConfig)config
|
||||
animated:(BOOL)animated
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ typedef NS_ENUM (NSInteger, IGListBatchUpdateTransactionMode) {
|
|||
@interface IGListBatchUpdateTransaction ()
|
||||
// Given
|
||||
@property (nonatomic, copy, readonly) UICollectionView *collectionView;
|
||||
@property (nonatomic, weak, readonly) id<IGListAdapterUpdaterCompatible> updater;
|
||||
@property (nonatomic, weak, readonly) IGListAdapterUpdater *updater;
|
||||
@property (nonatomic, weak, readonly, nullable) id<IGListAdapterUpdaterDelegate> 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<IGListAdapterUpdaterCompatible>)updater
|
||||
updater:(IGListAdapterUpdater *)updater
|
||||
delegate:(id<IGListAdapterUpdaterDelegate>)delegate
|
||||
config:(IGListUpdateTransactationConfig)config
|
||||
animated:(BOOL)animated
|
||||
|
|
|
|||
|
|
@ -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 <IGListUpdateTransactable>
|
||||
|
||||
- (instancetype)initWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock
|
||||
updater:(id<IGListAdapterUpdaterCompatible>)updater
|
||||
updater:(IGListAdapterUpdater *)updater
|
||||
delegate:(nullable id<IGListAdapterUpdaterDelegate>)delegate
|
||||
reloadBlock:(IGListReloadUpdateBlock)reloadBlock
|
||||
itemUpdateBlocks:(NSArray<IGListItemUpdateBlock> *)itemUpdateBlocks
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
@interface IGListReloadTransaction ()
|
||||
// Given
|
||||
@property (nonatomic, copy, readonly) UICollectionView *collectionView;
|
||||
@property (nonatomic, weak, readonly) id<IGListAdapterUpdaterCompatible> updater;
|
||||
@property (nonatomic, weak, readonly) IGListAdapterUpdater *updater;
|
||||
@property (nonatomic, weak, readonly, nullable) id<IGListAdapterUpdaterDelegate> delegate;
|
||||
@property (nonatomic, copy, readonly) IGListReloadUpdateBlock reloadBlock;
|
||||
@property (nonatomic, copy, readonly) NSArray<IGListItemUpdateBlock> *itemUpdateBlocks;
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
@implementation IGListReloadTransaction
|
||||
|
||||
- (instancetype)initWithCollectionViewBlock:(IGListCollectionViewBlock)collectionViewBlock
|
||||
updater:(id<IGListAdapterUpdaterCompatible>)updater
|
||||
updater:(IGListAdapterUpdater *)updater
|
||||
delegate:(id<IGListAdapterUpdaterDelegate>)delegate
|
||||
reloadBlock:(IGListReloadUpdateBlock)reloadBlock
|
||||
itemUpdateBlocks:(NSArray<IGListItemUpdateBlock> *)itemUpdateBlocks
|
||||
|
|
|
|||
|
|
@ -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<IGListUpdateTransactable>)buildWithConfig:(IGListUpdateTransactationConfig)config
|
||||
delegate:(nullable id<IGListAdapterUpdaterDelegate>)delegate
|
||||
updater:(id<IGListAdapterUpdaterCompatible>)updater;
|
||||
updater:(IGListAdapterUpdater *)updater;
|
||||
|
||||
- (BOOL)hasChanges;
|
||||
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ typedef NS_ENUM (NSInteger, IGListUpdateTransactionBuilderMode) {
|
|||
|
||||
- (nullable id<IGListUpdateTransactable>)buildWithConfig:(IGListUpdateTransactationConfig)config
|
||||
delegate:(nullable id<IGListAdapterUpdaterDelegate>)delegate
|
||||
updater:(id<IGListAdapterUpdaterCompatible>)updater {
|
||||
updater:(IGListAdapterUpdater *)updater {
|
||||
IGListCollectionViewBlock collectionViewBlock = self.collectionViewBlock;
|
||||
if (!collectionViewBlock) {
|
||||
return nil;
|
||||
|
|
|
|||
Loading…
Reference in a new issue