澎湃iPad上线版本

YFGIFImageView.m 4.7KB

    // // YFGIFImageView.m // UIImageView-PlayGIF // // Created by Yang Fei on 14-3-26. // Copyright (c) 2014年 yangfei.me. All rights reserved. // #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> #import <ImageIO/ImageIO.h> #import "YFGIFImageView.h" /**********************************************************************/ @interface YFGIFManager : NSObject @property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic, strong) NSHashTable *gifViewHashTable; + (YFGIFManager *)shared; - (void)stopGIFView:(YFGIFImageView *)view; @end @implementation YFGIFManager + (YFGIFManager *)shared{ static YFGIFManager *_sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedInstance = [[YFGIFManager alloc] init]; }); return _sharedInstance; } - (id)init{ self = [super init]; if (self) { _gifViewHashTable = [NSHashTable hashTableWithOptions:NSHashTableWeakMemory]; } return self; } - (void)play{ for (YFGIFImageView *imageView in _gifViewHashTable) { [imageView performSelector:@selector(play)]; } } - (void)stopDisplayLink{ if (self.displayLink) { [self.displayLink invalidate]; self.displayLink = nil; } } - (void)stopGIFView:(YFGIFImageView *)view{ [_gifViewHashTable removeObject:view]; if (_gifViewHashTable.count<1 && !_displayLink) { [self stopDisplayLink]; } } @end /**********************************************************************/ @interface YFGIFImageView(){ size_t _index; size_t _frameCount; float _timestamp; CGImageSourceRef _gifSourceRef; } @end @implementation YFGIFImageView - (void)removeFromSuperview{ if (self.isGIFPlaying) { [self stopGIF]; } [super removeFromSuperview]; } - (void)startGIF { [self startGIFWithRunLoopMode:NSDefaultRunLoopMode]; } - (void)startGIFWithRunLoopMode:(NSString * const)runLoopMode { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ if (![[YFGIFManager shared].gifViewHashTable containsObject:self]) { if ((self.gifData || self.gifPath)) { CGImageSourceRef gifSourceRef; if (self.gifData) { gifSourceRef = CGImageSourceCreateWithData((__bridge CFDataRef)(self.gifData), NULL); }else{ gifSourceRef = CGImageSourceCreateWithURL((__bridge CFURLRef)[NSURL fileURLWithPath:self.gifPath], NULL); } if (!gifSourceRef) { return; } dispatch_async(dispatch_get_main_queue(), ^{ [[YFGIFManager shared].gifViewHashTable addObject:self]; _gifSourceRef = gifSourceRef; _frameCount = CGImageSourceGetCount(gifSourceRef); }); } } }); if (![YFGIFManager shared].displayLink) { [YFGIFManager shared].displayLink = [CADisplayLink displayLinkWithTarget:[YFGIFManager shared] selector:@selector(play)]; [[YFGIFManager shared].displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode]; } } - (void)stopGIF{ if (_gifSourceRef) { CFRelease(_gifSourceRef); _gifSourceRef = nil; } [[YFGIFManager shared] stopGIFView:self]; } - (void)play{ float nextFrameDuration = [self frameDurationAtIndex:MIN(_index+1, _frameCount-1)]; if (_timestamp < nextFrameDuration) { _timestamp += [YFGIFManager shared].displayLink.duration; return; } _index ++; _index = _index%_frameCount; CGImageRef ref = CGImageSourceCreateImageAtIndex(_gifSourceRef, _index, NULL); self.layer.contents = (__bridge id)(ref); CGImageRelease(ref); _timestamp = 0; } - (BOOL)isGIFPlaying{ return _gifSourceRef?YES:NO; } - (float)frameDurationAtIndex:(size_t)index{ @try { CFDictionaryRef dictRef = CGImageSourceCopyPropertiesAtIndex(_gifSourceRef, index, NULL); NSDictionary *dict = (__bridge NSDictionary *)dictRef; NSDictionary *gifDict = (dict[(NSString *)kCGImagePropertyGIFDictionary]); NSNumber *unclampedDelayTime = gifDict[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; NSNumber *delayTime = gifDict[(NSString *)kCGImagePropertyGIFDelayTime]; if (dictRef) { CFRelease(dictRef); } if (unclampedDelayTime.floatValue) { return unclampedDelayTime.floatValue; }else if (delayTime.floatValue) { return delayTime.floatValue; }else{ return 1/24.0; } } @catch (NSException *exception) { TPLOG(@"gif error:%@",exception.reason); } @finally { } } @end