背景介绍:
APP启动页,常有静态图加链接,gif加链接,短视频等几种形式。
我们APP前期只有静态图这一种,功能已经实现。
之后,有了添加gif的需求,按理说,只要添加一个类型判断,按照数据类型,通过不同方法展示内容即可,但是一直不可以。。
出了这样的问题,下好的gif图,内容类型没错但是通过对应的gif方法显示的内容一直是一张静态图,并且还是模糊的。
因为之前的下载图片,以及显示图片的逻辑完全没问题,所以定位问题在显示gif的方法上,所以走了弯路,但是这条弯路是必然要走的。

下面开始我们的星辰大海,我们的目标是终结问题
先看源码--原来的代码

/**
* 下载新的图片
*/
+ (void)downloadAdImageWithUrl:(NSString *)imageUrl imageName:(NSString *)imageName imgLinkUrl:(NSString *)imgLinkUrl imgDeadline:(NSString *)imgDeadline imgStartline:(NSString *)imgstartline
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
UIImage *image = [UIImage imageWithData:data]; NSString *filePath = [self getFilePathWithImageName:imageName]; // 保存文件的名称
[UIImageJPEGRepresentation(image, 0) writeToFile:filePath atomically:YES];
if ([UIImageJPEGRepresentation(image, 0) writeToFile:filePath atomically:YES]) { // 保存成功
//判断保存下来的图片名字和本地沙盒中存在的图片是否一致,如果不一致,说明图片有更新,此时先删除沙盒中的旧图片,如果一致说明是删除缓存后再次下载,这时不需要进行删除操作,否则找不到已保存的图片
if (![imageName isEqualToString:[[NSUserDefaults standardUserDefaults] objectForKey:adImageName] ]) {
[self deleteOldImage];
} [[NSUserDefaults standardUserDefaults] setValue:imageName forKey:adImageName];
[[NSUserDefaults standardUserDefaults] setValue:imageUrl forKey:adUrl];
[[NSUserDefaults standardUserDefaults] setValue:imgDeadline forKey:adDeadline];
[[NSUserDefaults standardUserDefaults] setValue:imgstartline forKey:adstartline];
//保存图片
// [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:@"Deadline"];
// [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:@"startline"];
[[NSUserDefaults standardUserDefaults] synchronize];//立即写入 }else{
NSLog(@"保存失败");
} });
}
/**
* 通过在沙盒路径,获取gif图
*/
-(void)setImgFilePath:(NSString *)imgFilePath{
_imgFilePath = imgFilePath;
if ([_imgFilePath hasSuffix:@"gif"]) {
_adImageView.image = [UIImage sd_animatedGIFWithData:[NSData dataWithContentsOfFile:imgFilePath]];
}else{
_adImageView.image = [UIImage imageWithContentsOfFile:_imgFilePath];
} }

以上两个方法一个实现下载,一个实现显示,起初只有一张图片做启动图的时候,这种写法勉强用,虽然走了弯路,但是不会影响实现效果
但是新需求是需要加载gif,或许以后还有小视频

问题出来了
 gif一直下载不下来,起初修改了方法,毕竟gif有3M不小,所以换了下载方法,如下

/**
* 这个方法,下图片还行,你要是下载个大点的gif那就不合适了
*/
   NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
UIImage *image = [UIImage imageWithData:data];

那就改成下边的下载方法,适合稍大一点的文件下载

[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]]
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) { } else { }
}];

但是下载解决了问题后,发现还不能正常显示,但是项目中其他地方是没问题的啊,所以一直纠结于下面这个赋图的方法,其实是完全没问题的,只是能数据就不对了

 _adImageView.image = [UIImage sd_animatedGIFWithData:[NSData dataWithContentsOfFile:imgFilePath]];

读取数据没问题,只能是存数据的时候不对了

这个时候注意到,问题所在
 原因是下载的图片资源没有直接保存到某个路径下,而是先转成图片,然后图片转data保存了,多此一举了,重要的是,gif图的话,就把原来的资源都改变了,用的时候,获取的资源自然就出问题了,我们看代码

        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]];
UIImage *image = [UIImage imageWithData:data]; NSString *filePath = [self getFilePathWithImageName:imageName]; // 保存文件的名称
[UIImageJPEGRepresentation(image, 0) writeToFile:filePath atomically:YES];
if ([UIImageJPEGRepresentation(image, 0) writeToFile:filePath atomically:YES]){}

这是下载图片方法中的存储功能代码:获取data,转image,image写成data保存。我们可以看到多了一步,可能图片的时候,虽然多转换一步,图片资源没有改变,但是gif图用[UIImageJPEGRepresentation(image, 0) writeToFile:filePath atomically:YES];这个方法数据资源就改变了。所以导致图片虽然没问题,但是gif就不行了!

这儿其实不管他是何种类型资源直接保存data就好了。

下面是修改后的代码

+ (void)downloadAdImageWithUrl:(NSString *)imageUrl imageName:(NSString *)imageName imgLinkUrl:(NSString *)imgLinkUrl imgDeadline:(NSString *)imgDeadline imgStartline:(NSString *)imgstartline
{ [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:imageUrl]]
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) { NSString *filePath = [self getFilePathWithImageName:imageName]; // 保存文件的名称 //图片data直接存储,不需要转image然后再转data
if ([data writeToFile:filePath atomically:YES]) { // 保存成功
//判断保存下来的图片名字和本地沙盒中存在的图片是否一致,如果不一致,说明图片有更新,此时先删除沙盒中的旧图片,如果一致说明是删除缓存后再次下载,这时不需要进行删除操作,否则找不到已保存的图片
if (![imageName isEqualToString:[[NSUserDefaults standardUserDefaults] objectForKey:adImageName] ]) {
[self deleteOldImage];
} [[NSUserDefaults standardUserDefaults] setValue:imageName forKey:adImageName];
[[NSUserDefaults standardUserDefaults] setValue:imageUrl forKey:adUrl];
[[NSUserDefaults standardUserDefaults] setValue:imgDeadline forKey:adDeadline];
[[NSUserDefaults standardUserDefaults] setValue:imgstartline forKey:adstartline];
//保存图片
// [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:@"Deadline"];
// [[NSUserDefaults standardUserDefaults] setValue:@"" forKey:@"startline"];
[[NSUserDefaults standardUserDefaults] synchronize];//立即写入 }else{
NSLog(@"保存失败");
} } else { }
}];
return;
}

测试之后,正常显示gif。。。问题得以解决!

总结,问题往往就在你以为不可能出错的地方!

作者流浪

查看文章

iOS启动图-从网络获取的gif图,在本地一直是没有动画,还模糊的的更多相关文章

  1. Android LazyList 从网络获取图片并缓存

    原演示地址 本文内容 环境 演示 LazyList 从网络获取图片并缓存 参考资料 本文是 Github 上的一个演示,通过网络获取歌手专辑的缩略图,并显示在 ListView 控件中.该演示具备将缩 ...

  2. 用rose画UML图(用例图,活动图)

    用rose画UML图(用例图,活动图) 首先,安装rose2003,电脑从win8升到win10以后,发现win10并不支持rose2003的安装,换了rose2007以后,发现也不可以. 解决途径: ...

  3. iOS启动图和开屏广告图,类似网易

    iOS启动图和开屏广告图,类似网易 启动图是在iOS开发过程中必不可少的一个部分,很多app在启动图之后会有一张自定义的开屏广告图,点击该广告图可以跳转到广告图对应的页面.今天呢,和大家分享一下如何添 ...

  4. iOS最笨的办法实现无限轮播图(网络加载)

    iOS最笨的办法实现无限轮播图(网络加载) 简单的做了一下: 使用方法: 把 请求返回的 图片地址(字符串类型)放进数组中就行 可以使用SDWebImage(我就是用的这个)等..需要自己导入并引用, ...

  5. Android代码优化----PullToRefresh+universal-image-loader实现从网络获取数据并刷新

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  6. 关于iOS开发首次进入需要获取地理位置

    今天给大家简单介绍一下iOS开发过程中会遇到的获取地理位置的问题,(话不多说进入正题)这里给大家讲解一下两种在APPdelegate获取地理位置的方法: 一:首先是用系统的方法获取地理位置: 1. 首 ...

  7. Android & iOS 启动画面工具

    感谢Aone!为我们开发了如此便捷的工具!! 以下为原文:  Android & iOS 启动画面工具 下载:OneSplash.启动画面工具.Aone.20190318.zip 说明:这一个 ...

  8. Android ListView 和 ***Adapter 从本地/网络获取歌曲列表

    本文内容 环境 项目结构 测试数据 演示 1:SimpleAdapter 演示 2:BaseAdapter 演示 3:CustomLazyList 演示 4:CustomLazyCompleteLis ...

  9. Android Volley 库通过网络获取 JSON 数据

    本文内容 什么是 Volley 库 Volley 能做什么 Volley 架构 环境 演示 Volley 库通过网络获取 JSON 数据 参考资料 Android 关于网络操作一般都会介绍 HttpC ...

随机推荐

  1. HTML-标签:图片 超链接

    [img图片标签] 1,src属性:表示图片所在的路径. [路径的表示方式] ① 网络图片地址.并不建议使用. ② 可以使用图片的绝对路径.但是严禁使用绝对路径,因为绝对路径使用file://协议,网 ...

  2. ubuntu14.04 64位安装H3C iNode客户端

    环境: OS:ubuntu14.04LTS 64位 iNode: iNode2.40-R0162 for linux(iNode只有32位的,而且是很久以前的版本) 安装方法: 第一种: 检查本机是6 ...

  3. JQuery中的回调对象

    JQuery中的回调对象 回调对象(Callbacks object)模块是JQuery中的一个很基础的模块,很多其他的模块(比如Deferred.Ajax等)都依赖于Callbacks模块的实现.本 ...

  4. 关于excel的导入导出

    目前为方便操作,很多系统都增加了批量导入导出的功能.文件导入导出一般的格式都是excel,现将常用设计用例总结如下:   批量导入 一.模板检查检测:一般excel导入,都会提供模板下载功能 1.模板 ...

  5. Entity Framework - 基于外键关联的单向一对一关系

    代码的世界,原以为世界关系很简单,确道是关系无处不在.NET世界里ORM框架中EntityFramework作为其中翘楚,大大解放了搬砖工作的重复工作,着实提高了不少生产力,而也碰到过不少问题!比如关 ...

  6. java 面试,java 后端面试,数据库方面对初级和高级程序员的要求

    本内容摘自 java web轻量级开发面试教程 对于合格的程序员,需要有基本的数据库操作技能,具体体现在以下三个方面. l  第一,针对一类数据库(比如MySQL.Oracle.SQL Server等 ...

  7. The C++ Programming Language 学习笔记 第四章 类型和声明

    1.关于main 函数中的 return 0 C99标准中,main 函数的返回值类型必须是 int ,这样返回值才能传递给程序的激活者(如操作系统).如果 main 函数的最后没有写 return ...

  8. JVM内存结构和6大区域

    摘自 http://www.iteye.com/news/30350 对于我们一般理解的计算机内存,它算是CPU与计算机打交道最频繁的区域,所有数据都是先经过硬盘至内存,然后由CPU再从内存中获取数据 ...

  9. [2012-06-21]结合find的awk

    源起:http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=3754423&page=1&extra=#pid221729 ...

  10. 基于redis的延迟消息队列设计

    需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...