1616
1717#pragma mark - SPI
1818
19+ #define kCGImageAnimationStatus_Uninitialized -1
20+
1921@protocol CALayerProtocol <NSObject >
2022@property (nullable , strong ) id contents;
2123@property CGFloat contentsScale;
@@ -24,6 +26,13 @@ @protocol CALayerProtocol <NSObject>
2426@protocol UIViewProtocol <NSObject >
2527@property (nonatomic , strong , readonly ) id <CALayerProtocol> layer;
2628@property (nonatomic , assign ) SDImageScaleMode contentMode;
29+ @property (nonatomic , readonly ) id <UIViewProtocol> superview;
30+ @property (nonatomic , readonly , copy ) NSArray <id<UIViewProtocol>> *subviews;
31+ @property (nonatomic , readonly ) id window;
32+ @property (nonatomic ) CGFloat alpha;
33+ @property (nonatomic , getter =isHidden) BOOL hidden;
34+ @property (nonatomic , getter =isOpaque) BOOL opaque;
35+
2736@end
2837
2938@interface WKInterfaceObject ()
@@ -44,6 +53,14 @@ @interface SDAnimatedImageStatus : NSObject
4453
4554@implementation SDAnimatedImageStatus
4655
56+ - (instancetype )init {
57+ self = [super init ];
58+ if (self) {
59+ _animationStatus = kCGImageAnimationStatus_Uninitialized ;
60+ }
61+ return self;
62+ }
63+
4764@end
4865
4966@interface SDAnimatedImageInterface () {
@@ -59,6 +76,8 @@ @interface SDAnimatedImageInterface () {
5976@property (nonatomic , assign ) CGFloat animatedImageScale;
6077@property (nonatomic , strong ) SDAnimatedImageStatus *currentStatus;
6178@property (nonatomic , strong ) NSNumber *animationRepeatCount;
79+ @property (nonatomic , assign , getter =isAnimatedFormat) BOOL animatedFormat;
80+ @property (nonatomic , assign , getter =isAnimating) BOOL animating;
6281
6382@end
6483
@@ -105,6 +124,8 @@ - (void)setImage:(UIImage *)image {
105124 }
106125 _image = image;
107126
127+ // Stop animating
128+ [self stopBuiltInAnimation ];
108129 // Reset all value
109130 [self resetAnimatedImage ];
110131
@@ -126,15 +147,29 @@ - (void)setImage:(UIImage *)image {
126147 NSData *animatedImageData = animatedImage.animatedImageData ;
127148 SDImageFormat format = [NSData sd_imageFormatForImageData: animatedImageData];
128149 if (format == SDImageFormatGIF || format == SDImageFormatPNG) {
129- [self startBuiltInAnimationWithImage: animatedImage];
150+ self.animatedFormat = YES ;
151+ [self startBuiltInAnimation ];
152+ } else {
153+ self.animatedFormat = NO ;
154+ [self stopBuiltInAnimation ];
130155 }
131-
132- // Update should animate
133- [self updateShouldAnimate ];
134156 }
135157}
136158
137- - (void )startBuiltInAnimationWithImage : (UIImage<SDAnimatedImage> *)animatedImage {
159+ - (void )updateAnimation {
160+ [self updateShouldAnimate ];
161+ if (self.currentStatus .shouldAnimate ) {
162+ [self startBuiltInAnimation ];
163+ } else {
164+ [self stopBuiltInAnimation ];
165+ }
166+ }
167+
168+ - (void )startBuiltInAnimation {
169+ if (self.currentStatus && self.currentStatus .animationStatus == 0 ) {
170+ return ;
171+ }
172+ UIImage<SDAnimatedImage> *animatedImage = self.animatedImage ;
138173 NSData *animatedImageData = animatedImage.animatedImageData ;
139174 NSUInteger maxLoopCount;
140175 if (self.animationRepeatCount != nil ) {
@@ -148,7 +183,7 @@ - (void)startBuiltInAnimationWithImage:(UIImage<SDAnimatedImage> *)animatedImage
148183 maxLoopCount = ((__bridge NSNumber *)kCFNumberPositiveInfinity ).unsignedIntegerValue - 1 ;
149184 }
150185 NSDictionary *options = @{(__bridge NSString *)kCGImageAnimationLoopCount : @(maxLoopCount)};
151- SDAnimatedImageStatus *status = [SDAnimatedImageStatus new ];
186+ SDAnimatedImageStatus *status = [[ SDAnimatedImageStatus alloc ] init ];
152187 status.shouldAnimate = YES ;
153188 __weak typeof (self) wself = self;
154189 status.animationStatus = CGAnimateImageDataWithBlock ((__bridge CFDataRef)animatedImageData, (__bridge CFDictionaryRef)options, ^(size_t index, CGImageRef _Nonnull imageRef, bool * _Nonnull stop) {
@@ -171,6 +206,11 @@ - (void)startBuiltInAnimationWithImage:(UIImage<SDAnimatedImage> *)animatedImage
171206 self.currentStatus = status;
172207}
173208
209+ - (void )stopBuiltInAnimation {
210+ self.currentStatus .shouldAnimate = NO ;
211+ self.currentStatus .animationStatus = kCGImageAnimationStatus_Uninitialized ;
212+ }
213+
174214- (void )displayLayer {
175215 if (self.currentFrame ) {
176216 id <CALayerProtocol> layer = [self _interfaceView ].layer ;
@@ -184,44 +224,43 @@ - (void)resetAnimatedImage
184224 self.animatedImage = nil ;
185225 self.totalFrameCount = 0 ;
186226 self.totalLoopCount = 0 ;
187- // reset current state
188- self.currentStatus .shouldAnimate = NO ;
189- self.currentStatus = nil ;
190- [self resetCurrentFrameIndex ];
191- self.animatedImageScale = 1 ;
192- }
193-
194- - (void )resetCurrentFrameIndex
195- {
196227 self.currentFrame = nil ;
197228 self.currentFrameIndex = 0 ;
198229 self.currentLoopCount = 0 ;
230+ self.animatedImageScale = 1 ;
231+ self.animatedFormat = NO ;
232+ self.currentStatus = nil ;
199233}
200234
201235- (void )updateShouldAnimate
202236{
203- self.currentStatus .shouldAnimate = self.animatedImage && self.totalFrameCount > 1 ;
237+ id <UIViewProtocol> view = [self _interfaceView ];
238+ BOOL isVisible = view.window && view.superview && ![view isHidden ] && view.alpha > 0.0 ;
239+ self.currentStatus .shouldAnimate = self.isAnimating && self.animatedImage && self.isAnimatedFormat && self.totalFrameCount > 1 && isVisible;
204240}
205241
206242- (void )startAnimating {
243+ self.animating = YES ;
207244 if (self.animatedImage ) {
208- self. currentStatus . shouldAnimate = YES ;
245+ [ self startBuiltInAnimation ] ;
209246 } else if (_image.images .count > 0 ) {
210247 [super startAnimating ];
211248 }
212249}
213250
214251- (void )startAnimatingWithImagesInRange : (NSRange )imageRange duration : (NSTimeInterval )duration repeatCount : (NSInteger )repeatCount {
252+ self.animating = YES ;
215253 if (self.animatedImage ) {
216- self. currentStatus . shouldAnimate = YES ;
254+ [ self startBuiltInAnimation ] ;
217255 } else if (_image.images .count > 0 ) {
218256 [super startAnimatingWithImagesInRange: imageRange duration: duration repeatCount: repeatCount];
219257 }
220258}
221259
222260- (void )stopAnimating {
261+ self.animating = NO ;
223262 if (self.animatedImage ) {
224- self. currentStatus . shouldAnimate = NO ;
263+ [ self stopBuiltInAnimation ] ;
225264 } else if (_image.images .count > 0 ) {
226265 [super stopAnimating ];
227266 }
0 commit comments