From 7b02207537d35bfa1714bf8beafc921f717d100a Mon Sep 17 00:00:00 2001 From: 单军华 Date: Wed, 11 Jul 2018 10:47:42 +0800 Subject: [PATCH] 首次上传 --- screendisplay/Pods/YYImage/YYImage/YYAnimatedImageView.m | 672 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 672 insertions(+), 0 deletions(-) diff --git a/screendisplay/Pods/YYImage/YYImage/YYAnimatedImageView.m b/screendisplay/Pods/YYImage/YYImage/YYAnimatedImageView.m new file mode 100755 index 0000000..5f2bcb4 --- /dev/null +++ b/screendisplay/Pods/YYImage/YYImage/YYAnimatedImageView.m @@ -0,0 +1,672 @@ +// +// YYAnimatedImageView.m +// YYImage <https://github.com/ibireme/YYImage> +// +// Created by ibireme on 14/10/19. +// Copyright (c) 2015 ibireme. +// +// This source code is licensed under the MIT-style license found in the +// LICENSE file in the root directory of this source tree. +// + +#import "YYAnimatedImageView.h" +#import "YYImageCoder.h" +#import <pthread.h> +#import <mach/mach.h> + + +#define BUFFER_SIZE (10 * 1024 * 1024) // 10MB (minimum memory buffer size) + +#define LOCK(...) dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER); \ +__VA_ARGS__; \ +dispatch_semaphore_signal(self->_lock); + +#define LOCK_VIEW(...) dispatch_semaphore_wait(view->_lock, DISPATCH_TIME_FOREVER); \ +__VA_ARGS__; \ +dispatch_semaphore_signal(view->_lock); + + +static int64_t _YYDeviceMemoryTotal() { + int64_t mem = [[NSProcessInfo processInfo] physicalMemory]; + if (mem < -1) mem = -1; + return mem; +} + +static int64_t _YYDeviceMemoryFree() { + mach_port_t host_port = mach_host_self(); + mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); + vm_size_t page_size; + vm_statistics_data_t vm_stat; + kern_return_t kern; + + kern = host_page_size(host_port, &page_size); + if (kern != KERN_SUCCESS) return -1; + kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); + if (kern != KERN_SUCCESS) return -1; + return vm_stat.free_count * page_size; +} + +/** + A proxy used to hold a weak object. + It can be used to avoid retain cycles, such as the target in NSTimer or CADisplayLink. + */ +@interface _YYImageWeakProxy : NSProxy +@property (nonatomic, weak, readonly) id target; +- (instancetype)initWithTarget:(id)target; ++ (instancetype)proxyWithTarget:(id)target; +@end + +@implementation _YYImageWeakProxy +- (instancetype)initWithTarget:(id)target { + _target = target; + return self; +} ++ (instancetype)proxyWithTarget:(id)target { + return [[_YYImageWeakProxy alloc] initWithTarget:target]; +} +- (id)forwardingTargetForSelector:(SEL)selector { + return _target; +} +- (void)forwardInvocation:(NSInvocation *)invocation { + void *null = NULL; + [invocation setReturnValue:&null]; +} +- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { + return [NSObject instanceMethodSignatureForSelector:@selector(init)]; +} +- (BOOL)respondsToSelector:(SEL)aSelector { + return [_target respondsToSelector:aSelector]; +} +- (BOOL)isEqual:(id)object { + return [_target isEqual:object]; +} +- (NSUInteger)hash { + return [_target hash]; +} +- (Class)superclass { + return [_target superclass]; +} +- (Class)class { + return [_target class]; +} +- (BOOL)isKindOfClass:(Class)aClass { + return [_target isKindOfClass:aClass]; +} +- (BOOL)isMemberOfClass:(Class)aClass { + return [_target isMemberOfClass:aClass]; +} +- (BOOL)conformsToProtocol:(Protocol *)aProtocol { + return [_target conformsToProtocol:aProtocol]; +} +- (BOOL)isProxy { + return YES; +} +- (NSString *)description { + return [_target description]; +} +- (NSString *)debugDescription { + return [_target debugDescription]; +} +@end + + + + +typedef NS_ENUM(NSUInteger, YYAnimatedImageType) { + YYAnimatedImageTypeNone = 0, + YYAnimatedImageTypeImage, + YYAnimatedImageTypeHighlightedImage, + YYAnimatedImageTypeImages, + YYAnimatedImageTypeHighlightedImages, +}; + +@interface YYAnimatedImageView() { + @package + UIImage <YYAnimatedImage> *_curAnimatedImage; + + dispatch_once_t _onceToken; + dispatch_semaphore_t _lock; ///< lock for _buffer + NSOperationQueue *_requestQueue; ///< image request queue, serial + + CADisplayLink *_link; ///< ticker for change frame + NSTimeInterval _time; ///< time after last frame + + UIImage *_curFrame; ///< current frame to display + NSUInteger _curIndex; ///< current frame index (from 0) + NSUInteger _totalFrameCount; ///< total frame count + + BOOL _loopEnd; ///< whether the loop is end. + NSUInteger _curLoop; ///< current loop count (from 0) + NSUInteger _totalLoop; ///< total loop count, 0 means infinity + + NSMutableDictionary *_buffer; ///< frame buffer + BOOL _bufferMiss; ///< whether miss frame on last opportunity + NSUInteger _maxBufferCount; ///< maximum buffer count + NSInteger _incrBufferCount; ///< current allowed buffer count (will increase by step) + + CGRect _curContentsRect; + BOOL _curImageHasContentsRect; ///< image has implementated "animatedImageContentsRectAtIndex:" +} +@property (nonatomic, readwrite) BOOL currentIsPlayingAnimation; +- (void)calcMaxBufferCount; +@end + +/// An operation for image fetch +@interface _YYAnimatedImageViewFetchOperation : NSOperation +@property (nonatomic, weak) YYAnimatedImageView *view; +@property (nonatomic, assign) NSUInteger nextIndex; +@property (nonatomic, strong) UIImage <YYAnimatedImage> *curImage; +@end + +@implementation _YYAnimatedImageViewFetchOperation +- (void)main { + __strong YYAnimatedImageView *view = _view; + if (!view) return; + if ([self isCancelled]) return; + view->_incrBufferCount++; + if (view->_incrBufferCount == 0) [view calcMaxBufferCount]; + if (view->_incrBufferCount > (NSInteger)view->_maxBufferCount) { + view->_incrBufferCount = view->_maxBufferCount; + } + NSUInteger idx = _nextIndex; + NSUInteger max = view->_incrBufferCount < 1 ? 1 : view->_incrBufferCount; + NSUInteger total = view->_totalFrameCount; + view = nil; + + for (int i = 0; i < max; i++, idx++) { + @autoreleasepool { + if (idx >= total) idx = 0; + if ([self isCancelled]) break; + __strong YYAnimatedImageView *view = _view; + if (!view) break; + LOCK_VIEW(BOOL miss = (view->_buffer[@(idx)] == nil)); + + if (miss) { + UIImage *img = [_curImage animatedImageFrameAtIndex:idx]; + img = img.yy_imageByDecoded; + if ([self isCancelled]) break; + LOCK_VIEW(view->_buffer[@(idx)] = img ? img : [NSNull null]); + view = nil; + } + } + } +} +@end + +@implementation YYAnimatedImageView + +- (instancetype)init { + self = [super init]; + _runloopMode = NSRunLoopCommonModes; + _autoPlayAnimatedImage = YES; + return self; +} + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + _runloopMode = NSRunLoopCommonModes; + _autoPlayAnimatedImage = YES; + return self; +} + +- (instancetype)initWithImage:(UIImage *)image { + self = [super init]; + _runloopMode = NSRunLoopCommonModes; + _autoPlayAnimatedImage = YES; + self.frame = (CGRect) {CGPointZero, image.size }; + self.image = image; + return self; +} + +- (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highlightedImage { + self = [super init]; + _runloopMode = NSRunLoopCommonModes; + _autoPlayAnimatedImage = YES; + CGSize size = image ? image.size : highlightedImage.size; + self.frame = (CGRect) {CGPointZero, size }; + self.image = image; + self.highlightedImage = highlightedImage; + return self; +} + +// init the animated params. +- (void)resetAnimated { + dispatch_once(&_onceToken, ^{ + _lock = dispatch_semaphore_create(1); + _buffer = [NSMutableDictionary new]; + _requestQueue = [[NSOperationQueue alloc] init]; + _requestQueue.maxConcurrentOperationCount = 1; + _link = [CADisplayLink displayLinkWithTarget:[_YYImageWeakProxy proxyWithTarget:self] selector:@selector(step:)]; + if (_runloopMode) { + [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:_runloopMode]; + } + _link.paused = YES; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; + }); + + [_requestQueue cancelAllOperations]; + LOCK( + if (_buffer.count) { + NSMutableDictionary *holder = _buffer; + _buffer = [NSMutableDictionary new]; + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ + // Capture the dictionary to global queue, + // release these images in background to avoid blocking UI thread. + [holder class]; + }); + } + ); + _link.paused = YES; + _time = 0; + if (_curIndex != 0) { + [self willChangeValueForKey:@"currentAnimatedImageIndex"]; + _curIndex = 0; + [self didChangeValueForKey:@"currentAnimatedImageIndex"]; + } + _curAnimatedImage = nil; + _curFrame = nil; + _curLoop = 0; + _totalLoop = 0; + _totalFrameCount = 1; + _loopEnd = NO; + _bufferMiss = NO; + _incrBufferCount = 0; +} + +- (void)setImage:(UIImage *)image { + if (self.image == image) return; + [self setImage:image withType:YYAnimatedImageTypeImage]; +} + +- (void)setHighlightedImage:(UIImage *)highlightedImage { + if (self.highlightedImage == highlightedImage) return; + [self setImage:highlightedImage withType:YYAnimatedImageTypeHighlightedImage]; +} + +- (void)setAnimationImages:(NSArray *)animationImages { + if (self.animationImages == animationImages) return; + [self setImage:animationImages withType:YYAnimatedImageTypeImages]; +} + +- (void)setHighlightedAnimationImages:(NSArray *)highlightedAnimationImages { + if (self.highlightedAnimationImages == highlightedAnimationImages) return; + [self setImage:highlightedAnimationImages withType:YYAnimatedImageTypeHighlightedImages]; +} + +- (void)setHighlighted:(BOOL)highlighted { + [super setHighlighted:highlighted]; + if (_link) [self resetAnimated]; + [self imageChanged]; +} + +- (id)imageForType:(YYAnimatedImageType)type { + switch (type) { + case YYAnimatedImageTypeNone: return nil; + case YYAnimatedImageTypeImage: return self.image; + case YYAnimatedImageTypeHighlightedImage: return self.highlightedImage; + case YYAnimatedImageTypeImages: return self.animationImages; + case YYAnimatedImageTypeHighlightedImages: return self.highlightedAnimationImages; + } + return nil; +} + +- (YYAnimatedImageType)currentImageType { + YYAnimatedImageType curType = YYAnimatedImageTypeNone; + if (self.highlighted) { + if (self.highlightedAnimationImages.count) curType = YYAnimatedImageTypeHighlightedImages; + else if (self.highlightedImage) curType = YYAnimatedImageTypeHighlightedImage; + } + if (curType == YYAnimatedImageTypeNone) { + if (self.animationImages.count) curType = YYAnimatedImageTypeImages; + else if (self.image) curType = YYAnimatedImageTypeImage; + } + return curType; +} + +- (void)setImage:(id)image withType:(YYAnimatedImageType)type { + [self stopAnimating]; + if (_link) [self resetAnimated]; + _curFrame = nil; + switch (type) { + case YYAnimatedImageTypeNone: break; + case YYAnimatedImageTypeImage: super.image = image; break; + case YYAnimatedImageTypeHighlightedImage: super.highlightedImage = image; break; + case YYAnimatedImageTypeImages: super.animationImages = image; break; + case YYAnimatedImageTypeHighlightedImages: super.highlightedAnimationImages = image; break; + } + [self imageChanged]; +} + +- (void)imageChanged { + YYAnimatedImageType newType = [self currentImageType]; + id newVisibleImage = [self imageForType:newType]; + NSUInteger newImageFrameCount = 0; + BOOL hasContentsRect = NO; + if ([newVisibleImage isKindOfClass:[UIImage class]] && + [newVisibleImage conformsToProtocol:@protocol(YYAnimatedImage)]) { + newImageFrameCount = ((UIImage<YYAnimatedImage> *) newVisibleImage).animatedImageFrameCount; + if (newImageFrameCount > 1) { + hasContentsRect = [((UIImage<YYAnimatedImage> *) newVisibleImage) respondsToSelector:@selector(animatedImageContentsRectAtIndex:)]; + } + } + if (!hasContentsRect && _curImageHasContentsRect) { + if (!CGRectEqualToRect(self.layer.contentsRect, CGRectMake(0, 0, 1, 1)) ) { + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + self.layer.contentsRect = CGRectMake(0, 0, 1, 1); + [CATransaction commit]; + } + } + _curImageHasContentsRect = hasContentsRect; + if (hasContentsRect) { + CGRect rect = [((UIImage<YYAnimatedImage> *) newVisibleImage) animatedImageContentsRectAtIndex:0]; + [self setContentsRect:rect forImage:newVisibleImage]; + } + + if (newImageFrameCount > 1) { + [self resetAnimated]; + _curAnimatedImage = newVisibleImage; + _curFrame = newVisibleImage; + _totalLoop = _curAnimatedImage.animatedImageLoopCount; + _totalFrameCount = _curAnimatedImage.animatedImageFrameCount; + [self calcMaxBufferCount]; + } + [self setNeedsDisplay]; + [self didMoved]; +} + +// dynamically adjust buffer size for current memory. +- (void)calcMaxBufferCount { + int64_t bytes = (int64_t)_curAnimatedImage.animatedImageBytesPerFrame; + if (bytes == 0) bytes = 1024; + + int64_t total = _YYDeviceMemoryTotal(); + int64_t free = _YYDeviceMemoryFree(); + int64_t max = MIN(total * 0.2, free * 0.6); + max = MAX(max, BUFFER_SIZE); + if (_maxBufferSize) max = max > _maxBufferSize ? _maxBufferSize : max; + double maxBufferCount = (double)max / (double)bytes; + if (maxBufferCount < 1) maxBufferCount = 1; + else if (maxBufferCount > 512) maxBufferCount = 512; + _maxBufferCount = maxBufferCount; +} + +- (void)dealloc { + [_requestQueue cancelAllOperations]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; + [_link invalidate]; +} + +- (BOOL)isAnimating { + return self.currentIsPlayingAnimation; +} + +- (void)stopAnimating { + [super stopAnimating]; + [_requestQueue cancelAllOperations]; + _link.paused = YES; + self.currentIsPlayingAnimation = NO; +} + +- (void)startAnimating { + YYAnimatedImageType type = [self currentImageType]; + if (type == YYAnimatedImageTypeImages || type == YYAnimatedImageTypeHighlightedImages) { + NSArray *images = [self imageForType:type]; + if (images.count > 0) { + [super startAnimating]; + self.currentIsPlayingAnimation = YES; + } + } else { + if (_curAnimatedImage && _link.paused) { + _curLoop = 0; + _loopEnd = NO; + _link.paused = NO; + self.currentIsPlayingAnimation = YES; + } + } +} + +- (void)didReceiveMemoryWarning:(NSNotification *)notification { + [_requestQueue cancelAllOperations]; + [_requestQueue addOperationWithBlock: ^{ + _incrBufferCount = -60 - (int)(arc4random() % 120); // about 1~3 seconds to grow back.. + NSNumber *next = @((_curIndex + 1) % _totalFrameCount); + LOCK( + NSArray * keys = _buffer.allKeys; + for (NSNumber * key in keys) { + if (![key isEqualToNumber:next]) { // keep the next frame for smoothly animation + [_buffer removeObjectForKey:key]; + } + } + )//LOCK + }]; +} + +- (void)didEnterBackground:(NSNotification *)notification { + [_requestQueue cancelAllOperations]; + NSNumber *next = @((_curIndex + 1) % _totalFrameCount); + LOCK( + NSArray * keys = _buffer.allKeys; + for (NSNumber * key in keys) { + if (![key isEqualToNumber:next]) { // keep the next frame for smoothly animation + [_buffer removeObjectForKey:key]; + } + } + )//LOCK +} + +- (void)step:(CADisplayLink *)link { + UIImage <YYAnimatedImage> *image = _curAnimatedImage; + NSMutableDictionary *buffer = _buffer; + UIImage *bufferedImage = nil; + NSUInteger nextIndex = (_curIndex + 1) % _totalFrameCount; + BOOL bufferIsFull = NO; + + if (!image) return; + if (_loopEnd) { // view will keep in last frame + [self stopAnimating]; + return; + } + + NSTimeInterval delay = 0; + if (!_bufferMiss) { + _time += link.duration; + delay = [image animatedImageDurationAtIndex:_curIndex]; + if (_time < delay) return; + _time -= delay; + if (nextIndex == 0) { + _curLoop++; + if (_curLoop >= _totalLoop && _totalLoop != 0) { + _loopEnd = YES; + [self stopAnimating]; + [self.layer setNeedsDisplay]; // let system call `displayLayer:` before runloop sleep + return; // stop at last frame + } + } + delay = [image animatedImageDurationAtIndex:nextIndex]; + if (_time > delay) _time = delay; // do not jump over frame + } + LOCK( + bufferedImage = buffer[@(nextIndex)]; + if (bufferedImage) { + if ((int)_incrBufferCount < _totalFrameCount) { + [buffer removeObjectForKey:@(nextIndex)]; + } + [self willChangeValueForKey:@"currentAnimatedImageIndex"]; + _curIndex = nextIndex; + [self didChangeValueForKey:@"currentAnimatedImageIndex"]; + _curFrame = bufferedImage == (id)[NSNull null] ? nil : bufferedImage; + if (_curImageHasContentsRect) { + _curContentsRect = [image animatedImageContentsRectAtIndex:_curIndex]; + [self setContentsRect:_curContentsRect forImage:_curFrame]; + } + nextIndex = (_curIndex + 1) % _totalFrameCount; + _bufferMiss = NO; + if (buffer.count == _totalFrameCount) { + bufferIsFull = YES; + } + } else { + _bufferMiss = YES; + } + )//LOCK + + if (!_bufferMiss) { + [self.layer setNeedsDisplay]; // let system call `displayLayer:` before runloop sleep + } + + if (!bufferIsFull && _requestQueue.operationCount == 0) { // if some work not finished, wait for next opportunity + _YYAnimatedImageViewFetchOperation *operation = [_YYAnimatedImageViewFetchOperation new]; + operation.view = self; + operation.nextIndex = nextIndex; + operation.curImage = image; + [_requestQueue addOperation:operation]; + } +} + +- (void)displayLayer:(CALayer *)layer { + if (_curFrame) { + layer.contents = (__bridge id)_curFrame.CGImage; + } +} + +- (void)setContentsRect:(CGRect)rect forImage:(UIImage *)image{ + CGRect layerRect = CGRectMake(0, 0, 1, 1); + if (image) { + CGSize imageSize = image.size; + if (imageSize.width > 0.01 && imageSize.height > 0.01) { + layerRect.origin.x = rect.origin.x / imageSize.width; + layerRect.origin.y = rect.origin.y / imageSize.height; + layerRect.size.width = rect.size.width / imageSize.width; + layerRect.size.height = rect.size.height / imageSize.height; + layerRect = CGRectIntersection(layerRect, CGRectMake(0, 0, 1, 1)); + if (CGRectIsNull(layerRect) || CGRectIsEmpty(layerRect)) { + layerRect = CGRectMake(0, 0, 1, 1); + } + } + } + [CATransaction begin]; + [CATransaction setDisableActions:YES]; + self.layer.contentsRect = layerRect; + [CATransaction commit]; +} + +- (void)didMoved { + if (self.autoPlayAnimatedImage) { + if(self.superview && self.window) { + [self startAnimating]; + } else { + [self stopAnimating]; + } + } +} + +- (void)didMoveToWindow { + [super didMoveToWindow]; + [self didMoved]; +} + +- (void)didMoveToSuperview { + [super didMoveToSuperview]; + [self didMoved]; +} + +- (void)setCurrentAnimatedImageIndex:(NSUInteger)currentAnimatedImageIndex { + if (!_curAnimatedImage) return; + if (currentAnimatedImageIndex >= _curAnimatedImage.animatedImageFrameCount) return; + if (_curIndex == currentAnimatedImageIndex) return; + + void (^block)() = ^{ + LOCK( + [_requestQueue cancelAllOperations]; + [_buffer removeAllObjects]; + [self willChangeValueForKey:@"currentAnimatedImageIndex"]; + _curIndex = currentAnimatedImageIndex; + [self didChangeValueForKey:@"currentAnimatedImageIndex"]; + _curFrame = [_curAnimatedImage animatedImageFrameAtIndex:_curIndex]; + if (_curImageHasContentsRect) { + _curContentsRect = [_curAnimatedImage animatedImageContentsRectAtIndex:_curIndex]; + } + _time = 0; + _loopEnd = NO; + _bufferMiss = NO; + [self.layer setNeedsDisplay]; + )//LOCK + }; + + if (pthread_main_np()) { + block(); + } else { + dispatch_async(dispatch_get_main_queue(), block); + } +} + +- (NSUInteger)currentAnimatedImageIndex { + return _curIndex; +} + +- (void)setRunloopMode:(NSString *)runloopMode { + if ([_runloopMode isEqual:runloopMode]) return; + if (_link) { + if (_runloopMode) { + [_link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:_runloopMode]; + } + if (runloopMode.length) { + [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:runloopMode]; + } + } + _runloopMode = runloopMode.copy; +} + +#pragma mark - Override NSObject(NSKeyValueObservingCustomization) + ++ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { + if ([key isEqualToString:@"currentAnimatedImageIndex"]) { + return NO; + } + return [super automaticallyNotifiesObserversForKey:key]; +} + +#pragma mark - NSCoding + +- (instancetype)initWithCoder:(NSCoder *)aDecoder { + self = [super initWithCoder:aDecoder]; + _runloopMode = [aDecoder decodeObjectForKey:@"runloopMode"]; + if (_runloopMode.length == 0) _runloopMode = NSRunLoopCommonModes; + if ([aDecoder containsValueForKey:@"autoPlayAnimatedImage"]) { + _autoPlayAnimatedImage = [aDecoder decodeBoolForKey:@"autoPlayAnimatedImage"]; + } else { + _autoPlayAnimatedImage = YES; + } + + UIImage *image = [aDecoder decodeObjectForKey:@"YYAnimatedImage"]; + UIImage *highlightedImage = [aDecoder decodeObjectForKey:@"YYHighlightedAnimatedImage"]; + if (image) { + self.image = image; + [self setImage:image withType:YYAnimatedImageTypeImage]; + } + if (highlightedImage) { + self.highlightedImage = highlightedImage; + [self setImage:highlightedImage withType:YYAnimatedImageTypeHighlightedImage]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)aCoder { + [super encodeWithCoder:aCoder]; + [aCoder encodeObject:_runloopMode forKey:@"runloopMode"]; + [aCoder encodeBool:_autoPlayAnimatedImage forKey:@"autoPlayAnimatedImage"]; + + BOOL ani, multi; + ani = [self.image conformsToProtocol:@protocol(YYAnimatedImage)]; + multi = (ani && ((UIImage <YYAnimatedImage> *)self.image).animatedImageFrameCount > 1); + if (multi) [aCoder encodeObject:self.image forKey:@"YYAnimatedImage"]; + + ani = [self.highlightedImage conformsToProtocol:@protocol(YYAnimatedImage)]; + multi = (ani && ((UIImage <YYAnimatedImage> *)self.highlightedImage).animatedImageFrameCount > 1); + if (multi) [aCoder encodeObject:self.highlightedImage forKey:@"YYHighlightedAnimatedImage"]; +} + +@end -- Gitblit v1.8.0