Merge pull request #3053 from kinarobin/fix-race-condition-when-using-transition
Fix race condition when use transition but canceling an operation
This commit is contained in:
commit
19ca248e93
|
@ -34,6 +34,7 @@ typedef void(^SDSetImageBlock)(UIImage * _Nullable image, NSData * _Nullable ima
|
|||
/**
|
||||
* Get the current image operation key. Operation key is used to identify the different queries for one view instance (like UIButton).
|
||||
* See more about this in `SDWebImageContextSetImageOperationKey`.
|
||||
* If you cancel current image load, the key will be set to nil.
|
||||
* @note You can use method `UIView+WebCacheOperation` to investigate different queries' operation.
|
||||
*/
|
||||
@property (nonatomic, strong, readonly, nullable) NSString *sd_latestOperationKey;
|
||||
|
|
|
@ -203,6 +203,7 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
|
||||
- (void)sd_cancelCurrentImageLoad {
|
||||
[self sd_cancelImageLoadOperationWithKey:self.sd_latestOperationKey];
|
||||
self.sd_latestOperationKey = nil;
|
||||
}
|
||||
|
||||
- (void)sd_setImage:(UIImage *)image imageData:(NSData *)imageData basedOnClassOrViaCustomSetImageBlock:(SDSetImageBlock)setImageBlock cacheType:(SDImageCacheType)cacheType imageURL:(NSURL *)imageURL {
|
||||
|
@ -251,22 +252,38 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
if (transition) {
|
||||
#if SD_UIKIT
|
||||
[UIView transitionWithView:view duration:0 options:0 animations:^{
|
||||
if (!view.sd_latestOperationKey) {
|
||||
return;
|
||||
}
|
||||
// 0 duration to let UIKit render placeholder and prepares block
|
||||
if (transition.prepares) {
|
||||
transition.prepares(view, image, imageData, cacheType, imageURL);
|
||||
}
|
||||
} completion:^(BOOL finished) {
|
||||
[UIView transitionWithView:view duration:transition.duration options:transition.animationOptions animations:^{
|
||||
if (!view.sd_latestOperationKey) {
|
||||
return;
|
||||
}
|
||||
if (finalSetImageBlock && !transition.avoidAutoSetImage) {
|
||||
finalSetImageBlock(image, imageData, cacheType, imageURL);
|
||||
}
|
||||
if (transition.animations) {
|
||||
transition.animations(view, image);
|
||||
}
|
||||
} completion:transition.completion];
|
||||
} completion:^(BOOL finished) {
|
||||
if (!view.sd_latestOperationKey) {
|
||||
return;
|
||||
}
|
||||
if (transition.completion) {
|
||||
transition.completion(finished);
|
||||
}
|
||||
}];
|
||||
}];
|
||||
#elif SD_MAC
|
||||
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull prepareContext) {
|
||||
if (!view.sd_latestOperationKey) {
|
||||
return;
|
||||
}
|
||||
// 0 duration to let AppKit render placeholder and prepares block
|
||||
prepareContext.duration = 0;
|
||||
if (transition.prepares) {
|
||||
|
@ -274,11 +291,14 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
}
|
||||
} completionHandler:^{
|
||||
[NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
|
||||
if (!view.sd_latestOperationKey) {
|
||||
return;
|
||||
}
|
||||
context.duration = transition.duration;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
CAMediaTimingFunction *timingFunction = transition.timingFunction;
|
||||
#pragma clang diagnostic pop
|
||||
#pragma clang diagnostic pop
|
||||
if (!timingFunction) {
|
||||
timingFunction = SDTimingFunctionFromAnimationOptions(transition.animationOptions);
|
||||
}
|
||||
|
@ -295,6 +315,9 @@ const int64_t SDWebImageProgressUnitCountUnknown = 1LL;
|
|||
transition.animations(view, image);
|
||||
}
|
||||
} completionHandler:^{
|
||||
if (!view.sd_latestOperationKey) {
|
||||
return;
|
||||
}
|
||||
if (transition.completion) {
|
||||
transition.completion(YES);
|
||||
}
|
||||
|
|
|
@ -208,6 +208,7 @@
|
|||
[imageView sd_internalSetImageWithURL:originalImageURL placeholderImage:nil options:0 context:nil setImageBlock:nil progress:nil completed:nil];
|
||||
[imageView sd_cancelCurrentImageLoad];
|
||||
NSString *operationKey = NSStringFromClass(UIView.class);
|
||||
expect(imageView.sd_latestOperationKey).beNil();
|
||||
expect([imageView sd_imageLoadOperationForKey:operationKey]).beNil();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue