Merge pull request #3680 from dreampiggy/feature/wait_transition

Added `SDWebImageWaitTransition` to wait for transition finished and then callback `completedBlock`
This commit is contained in:
DreamPiggy 2024-02-24 17:06:37 +08:00 committed by GitHub
commit 00d58fa58f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 44 additions and 4 deletions

View File

@ -218,6 +218,15 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
* @note This options is UI level options, has no usage on ImageManager or other components.
*/
SDWebImageAvoidAutoCancelImage = 1 << 24,
/**
* By defaults, for `SDWebImageTransition`, we just submit to UI transition and inmeediatelly callback the final `completedBlock` (`SDExternalCompletionBlock/SDInternalCompletionBlock`).
* This may cause un-wanted behavior if you do another transition inside `completedBlock`, because the previous transition is still runnning and un-cancellable, which mass-up the UI status.
* For this case, you can pass this option, we will delay the final callback, until your transition end. So when you inside `completedBlock`, no any transition is running on image view and safe to submit new transition.
* @note Currently we do not support `pausable/cancellable` transition. But possible in the future by using the https://developer.apple.com/documentation/uikit/uiviewpropertyanimator.
* @note If you have complicated transition animation, just use `SDWebImageManager` and do UI state management by yourself, do not use the top-level API (`sd_setImageWithURL:`)
*/
SDWebImageWaitTransition = 1 << 25,
};

View File

@ -232,11 +232,11 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
#endif
dispatch_main_async_safe(^{
#if SD_UIKIT || SD_MAC
[self sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL];
[self sd_setImage:targetImage imageData:targetData options:options basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:transition cacheType:cacheType imageURL:imageURL callback:callCompletedBlockClosure];
#else
[self sd_setImage:targetImage imageData:targetData basedOnClassOrViaCustomSetImageBlock:setImageBlock cacheType:cacheType imageURL:imageURL];
#endif
callCompletedBlockClosure();
#endif
});
}];
[self sd_setImageLoadOperation:operation forKey:validOperationKey];
@ -263,9 +263,10 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
[self sd_cancelImageLoadOperationWithKey:self.sd_latestOperationKey];
}
// Set image logic without transition (like placeholder and watchOS)
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock cacheType:(SDImageCacheType)cacheType imageURL:(NSURL *)imageURL {
#if SD_UIKIT || SD_MAC
[self sd_setImage:image imageData:imageData basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:nil cacheType:cacheType imageURL:imageURL];
[self sd_setImage:image imageData:imageData options:0 basedOnClassOrViaCustomSetImageBlock:setImageBlock transition:nil cacheType:cacheType imageURL:imageURL callback:nil];
#else
// watchOS does not support view transition. Simplify the logic
if (setImageBlock) {
@ -277,8 +278,9 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
#endif
}
// Set image logic with transition
#if SD_UIKIT || SD_MAC
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock transition:(SDWebImageTransition *)transition cacheType:(SDImageCacheType)cacheType imageURL:(NSURL *)imageURL {
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData options:(SDWebImageOptions)options basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock transition:(SDWebImageTransition *)transition cacheType:(SDImageCacheType)cacheType imageURL:(NSURL *)imageURL callback:(SDWebImageNoParamsBlock)callback {
UIView *view = self;
SDSetImageBlock finalSetImageBlock;
if (setImageBlock) {
@ -306,6 +308,7 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
}
#endif
BOOL waitTransition = SD_OPTIONS_CONTAINS(options, SDWebImageWaitTransition);
if (transition) {
NSString *originalOperationKey = view.sd_latestOperationKey;
@ -336,6 +339,11 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
if (transition.completion) {
transition.completion(finished);
}
if (waitTransition) {
if (callback) {
callback();
}
}
}];
}];
#elif SD_MAC
@ -380,12 +388,35 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
if (transition.completion) {
transition.completion(YES);
}
if (waitTransition) {
if (callback) {
callback();
}
}
}];
}];
#endif
if (!waitTransition) {
if (callback) {
callback();
}
}
} else {
if (finalSetImageBlock) {
finalSetImageBlock(image, imageData, cacheType, imageURL);
// TODO, in 6.0
// for `waitTransition`, the `setImageBlock` will provide a extra `completionHandler` params
// Execute `callback` only after that completionHandler is called
if (waitTransition) {
if (callback) {
callback();
}
}
}
if (!waitTransition) {
if (callback) {
callback();
}
}
}
}