Ver código fonte

potentially problem when system load high: #79

ibireme 9 anos atrás
pai
commit
745a0b7f87

+ 13 - 3
YYWebImage/Categories/CALayer+YYWebImage.m

@@ -145,12 +145,15 @@ static int _YYWebImageSetterKey;
                 });
             };
             
+            __block int32_t newSentinel = 0;
+            __weak typeof(setter) weakSetter = nil;
             YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
                 __strong typeof(_self) self = _self;
                 BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
                 BOOL showFade = (options & YYWebImageOptionSetImageWithFadeAnimation);
                 dispatch_async(dispatch_get_main_queue(), ^{
-                    if (setImage && self) {
+                    BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
+                    if (setImage && self && !sentinelChanged) {
                         if (showFade) {
                             CATransition *transition = [CATransition animation];
                             transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime;
@@ -160,11 +163,18 @@ static int _YYWebImageSetterKey;
                         }
                         self.contents = (id)image.CGImage;
                     }
-                    if (completion) completion(image, url, from, stage, error);
+                    if (completion) {
+                        if (sentinelChanged) {
+                            completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
+                        } else {
+                            completion(image, url, from, stage, error);
+                        }
+                    }
                 });
             };
             
-            [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            weakSetter = setter;
         });
         
         

+ 13 - 3
YYWebImage/Categories/MKAnnotationView+YYWebImage.m

@@ -145,12 +145,15 @@ static int _YYWebImageSetterKey;
                 });
             };
             
+            __block int32_t newSentinel = 0;
+            __weak typeof(setter) weakSetter = nil;
             YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
                 __strong typeof(_self) self = _self;
                 BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
                 BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && !self.highlighted);
                 dispatch_async(dispatch_get_main_queue(), ^{
-                    if (setImage && self) {
+                    BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
+                    if (setImage && self && !sentinelChanged) {
                         if (showFade) {
                             CATransition *transition = [CATransition animation];
                             transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime;
@@ -160,11 +163,18 @@ static int _YYWebImageSetterKey;
                         }
                         self.image = image;
                     }
-                    if (completion) completion(image, url, from, stage, error);
+                    if (completion) {
+                        if (sentinelChanged) {
+                            completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
+                        } else {
+                            completion(image, url, from, stage, error);
+                        }
+                    }
                 });
             };
             
-            [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            weakSetter = setter;
         });
     });
 }

+ 26 - 6
YYWebImage/Categories/UIButton+YYWebImage.m

@@ -133,18 +133,28 @@ static int _YYWebImageBackgroundSetterKey;
                 });
             };
             
+            __block int32_t newSentinel = 0;
+            __weak typeof(setter) weakSetter = nil;
             YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
                 __strong typeof(_self) self = _self;
                 BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
                 dispatch_async(dispatch_get_main_queue(), ^{
-                    if (setImage && self) {
+                    BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
+                    if (setImage && self && !sentinelChanged) {
                         [self setImage:image forState:state.integerValue];
                     }
-                    if (completion) completion(image, url, from, stage, error);
+                    if (completion) {
+                        if (sentinelChanged) {
+                            completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
+                        } else {
+                            completion(image, url, from, stage, error);
+                        }
+                    }
                 });
             };
             
-            [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            weakSetter = setter;
         });
     });
 }
@@ -304,18 +314,28 @@ static int _YYWebImageBackgroundSetterKey;
                 });
             };
             
+            __block int32_t newSentinel = 0;
+            __weak typeof(setter) weakSetter = nil;
             YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
                 __strong typeof(_self) self = _self;
                 BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
                 dispatch_async(dispatch_get_main_queue(), ^{
-                    if (setImage && self) {
+                    BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
+                    if (setImage && self && !sentinelChanged) {
                         [self setBackgroundImage:image forState:state.integerValue];
                     }
-                    if (completion) completion(image, url, from, stage, error);
+                    if (completion) {
+                        if (sentinelChanged) {
+                            completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
+                        } else {
+                            completion(image, url, from, stage, error);
+                        }
+                    }
                 });
             };
             
-            [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            weakSetter = setter;
         });
     });
 }

+ 26 - 6
YYWebImage/Categories/UIImageView+YYWebImage.m

@@ -149,11 +149,14 @@ static int _YYWebImageHighlightedSetterKey;
                 });
             };
             
+            __block int32_t newSentinel = 0;
+            __weak typeof(setter) weakSetter = nil;
             YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
                 __strong typeof(_self) self = _self;
                 BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
                 dispatch_async(dispatch_get_main_queue(), ^{
-                    if (setImage && self) {
+                    BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
+                    if (setImage && self && !sentinelChanged) {
                         BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && !self.highlighted);
                         if (showFade) {
                             CATransition *transition = [CATransition animation];
@@ -164,11 +167,18 @@ static int _YYWebImageHighlightedSetterKey;
                         }
                         self.image = image;
                     }
-                    if (completion) completion(image, url, from, stage, error);
+                    if (completion) {
+                        if (sentinelChanged) {
+                            completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
+                        } else {
+                            completion(image, url, from, stage, error);
+                        }
+                    }
                 });
             };
             
-            [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            weakSetter = setter;
         });
     });
 }
@@ -303,12 +313,15 @@ static int _YYWebImageHighlightedSetterKey;
                 });
             };
             
+            __block int32_t newSentinel = 0;
+            __weak typeof(setter) weakSetter = nil;
             YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) {
                 __strong typeof(_self) self = _self;
                 BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage);
                 BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && self.highlighted);
                 dispatch_async(dispatch_get_main_queue(), ^{
-                    if (setImage && self) {
+                    BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel;
+                    if (setImage && self && !sentinelChanged) {
                         if (showFade) {
                             CATransition *transition = [CATransition animation];
                             transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime;
@@ -318,11 +331,18 @@ static int _YYWebImageHighlightedSetterKey;
                         }
                         self.highlightedImage = image;
                     }
-                    if (completion) completion(image, url, from, stage, error);
+                    if (completion) {
+                        if (sentinelChanged) {
+                            completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil);
+                        } else {
+                            completion(image, url, from, stage, error);
+                        }
+                    }
                 });
             };
             
-            [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion];
+            weakSetter = setter;
         });
     });
 }

+ 10 - 8
YYWebImage/Categories/_YYWebImageSetter.h

@@ -41,15 +41,17 @@ extern const NSTimeInterval _YYWebImageProgressiveFadeTime;
 @interface _YYWebImageSetter : NSObject
 /// Current image url.
 @property (nullable, nonatomic, readonly) NSURL *imageURL;
+/// Current sentinel.
+@property (nonatomic, readonly) int32_t sentinel;
 
-/// Create new operation for web image.
-- (void)setOperationWithSentinel:(int32_t)sentinel
-                             url:(nullable NSURL *)imageURL
-                         options:(YYWebImageOptions)options
-                         manager:(YYWebImageManager *)manager
-                        progress:(nullable YYWebImageProgressBlock)progress
-                       transform:(nullable YYWebImageTransformBlock)transform
-                      completion:(nullable YYWebImageCompletionBlock)completion;
+/// Create new operation for web image and return a sentinel value.
+- (int32_t)setOperationWithSentinel:(int32_t)sentinel
+                                url:(nullable NSURL *)imageURL
+                            options:(YYWebImageOptions)options
+                            manager:(YYWebImageManager *)manager
+                           progress:(nullable YYWebImageProgressBlock)progress
+                          transform:(nullable YYWebImageTransformBlock)transform
+                         completion:(nullable YYWebImageCompletionBlock)completion;
 
 /// Cancel and return a sentinel value. The imageURL will be set to nil.
 - (int32_t)cancel;

+ 10 - 9
YYWebImage/Categories/_YYWebImageSetter.m

@@ -43,16 +43,16 @@ const NSTimeInterval _YYWebImageProgressiveFadeTime = 0.4;
     [_operation cancel];
 }
 
-- (void)setOperationWithSentinel:(int32_t)sentinel
-                             url:(NSURL *)imageURL
-                         options:(YYWebImageOptions)options
-                         manager:(YYWebImageManager *)manager
-                        progress:(YYWebImageProgressBlock)progress
-                       transform:(YYWebImageTransformBlock)transform
-                      completion:(YYWebImageCompletionBlock)completion {
+- (int32_t)setOperationWithSentinel:(int32_t)sentinel
+                                url:(NSURL *)imageURL
+                            options:(YYWebImageOptions)options
+                            manager:(YYWebImageManager *)manager
+                           progress:(YYWebImageProgressBlock)progress
+                          transform:(YYWebImageTransformBlock)transform
+                         completion:(YYWebImageCompletionBlock)completion {
     if (sentinel != _sentinel) {
         if (completion) completion(nil, imageURL, YYWebImageFromNone, YYWebImageStageCancelled, nil);
-        return;
+        return _sentinel;
     }
     
     NSOperation *operation = [manager requestImageWithURL:imageURL options:options progress:progress transform:transform completion:completion];
@@ -65,11 +65,12 @@ const NSTimeInterval _YYWebImageProgressiveFadeTime = 0.4;
     if (sentinel == _sentinel) {
         if (_operation) [_operation cancel];
         _operation = operation;
-        OSAtomicIncrement32(&_sentinel);
+        sentinel = OSAtomicIncrement32(&_sentinel);
     } else {
         [operation cancel];
     }
     dispatch_semaphore_signal(_lock);
+    return sentinel;
 }
 
 - (int32_t)cancel {