在iOS中使用gif图片,多少来说有点麻烦。尽管使用第三方框架也未必能达到自己想要的结果,为了方便我们还是的使用。
本人推荐使用UIImageView+PlayGIF,有需要的小伙伴可以自行到git上找。如果小伙伴有更好的推荐,请写到评论里面。
UIImageView+PlayGIF 是UIImageView的分类,使用起来比较简单,这是几个.h文件的变量和方法:
@property (nonatomic, strong) NSString *gifPath;
@property (nonatomic, strong) NSData *gifData;
@property (nonatomic, strong) NSNumber *index,*frameCount,*timestamp;
- (void)startGIF;
- (void)startGIFWithRunLoopMode:(NSString * const)runLoopMode;
- (void)stopGIF;
- (BOOL)isGIFPlaying;
使用方法:
1. 包含头文件
#import "UIImageView+PlayGIF.h"
2. 设置imageview的gifpath 或者 gifData;_sellerRankView.gifPath = [[NSBundle mainBundle] pathForResource:imageString ofType:nil];
3.开始执行动画[_sellerRankView startGIF];
然后就ok了。
UIImageView+PlayGIF默认将线程加到mainRunLoop中,但是在 tableview中加载这个imageview,将会造成tableview在滚动时gif图片动画不能播放。此时只需要对UIImageView+PlayGIF稍做修改即可。
将:
- (void)startGIFWithRunLoopMode:(NSString * const)runLoopMode
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
if (![[PlayGIFManager shared].gifViewHashTable containsObject:self] && (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(), ^{
[[PlayGIFManager shared].gifViewHashTable addObject:self];
[[PlayGIFManager shared].gifSourceRefMapTable setObject:(__bridge id)(gifSourceRef) forKey:self];
self.frameCount = [NSNumber numberWithInteger:CGImageSourceGetCount(gifSourceRef)];
});
}
});
if (![PlayGIFManager shared].displayLink) {
[PlayGIFManager shared].displayLink = [CADisplayLink displayLinkWithTarget:[PlayGIFManager shared] selector:@selector(play)];
[[PlayGIFManager shared].displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:runLoopMode];
}
}
改为:
- (void)startGIFWithRunLoopMode:(NSString * const)runLoopMode
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
if (![[PlayGIFManager shared].gifViewHashTable containsObject:self] && (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(), ^{
[[PlayGIFManager shared].gifViewHashTable addObject:self];
[[PlayGIFManager shared].gifSourceRefMapTable setObject:(__bridge id)(gifSourceRef) forKey:self];
self.frameCount = [NSNumber numberWithInteger:CGImageSourceGetCount(gifSourceRef)];
});
}
});
if (![PlayGIFManager shared].displayLink) {
[PlayGIFManager shared].displayLink = [CADisplayLink displayLinkWithTarget:[PlayGIFManager shared] selector:@selector(play)];
[[PlayGIFManager shared].displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
}
此时如果我们为每个cell展示一张不同的gif图片时,会遇到循环引用的问题。这是因为在设置图片时我们掉用了 startGIF 这个方法。我们还需要在适当的时机去把starGIF方法暂停掉。这个时机个人觉得是在cell刚从界面进入缓存池的时候最为恰当,但是我始终找不到这个适当时机的方法。退而求其次,只能在
cellForRowAtIndexPath中进行判断,方法如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
HYTSellerDisplayCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SellerDisplay"forIndexPath:indexPath];
if ([cell.sellerRankView isGIFPlaying]) {
[cell.sellerRankView stopGIF];
}
HYTSeller *seller = self.datas[indexPath.row];
cell.seller = seller;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}