【第22期】观点:IT 行业加班,到底有没有价值?

iOS 开发中如何显示网络图片

原创 2015年07月10日 12:22:52
              by Fanxiushu  2015-07-10 转载或引用请注明原作者

 iOS开发中,使用UIImageView控件来显示图片,非常简单几句话就能显示一个完整的图片:
UIImageView* img =[[UIImageView alloc] initWithFrame:frame];
[superView addSubView:img];
img.image=[UIImage imageNamed:@"picture.png"];
这是图片在本地的情况,可是如果图片文件在网络上该如何实现呢?
你可以使用 NSData* data = [NSData dataWithContentsOfURL:URL];
然后NSData数据转化到 UIImage,
但是 dataWithContentsOfURL是同步获取数据,如果图片文件太大,会阻塞主线程,造成界面假死。
当然也可以使用别人开发的库,比如 SDWebImage就能很好的下载和缓存网络图片。
可是如果花不了多少精力能自己实现这个功能,我就会尽力自己实现来满足某些项目的要求,
这样看起来简洁好维护,更重要的是通过自己实现更能掌握核心部分。
自己实现关键是要解决网络同步传输问题。
然后你也许又想到一堆别人开发的网络库,比如AFNetworking,ASIHTTPRequest等等,
其实这些都用不着,直接用苹果原生SDK API就可以了,使用他的 NSURLConnection,
至少iOS的自带的网络API,比起windows平台下的WININET要简洁不少。

设计一个 UIImageView的Category类别类,在这个类别类中增加一个方法,比如setImageWithUrl,
这个方法就是我们需要实现的从网络下载并且显示到 UIImageView控件的方法。

 要在这个方法中异步下载网络图片,并且要实时显示下载进度,因此得做个NSURLConnection代理类,管理下载进度。

 定义的接口如下:
 @interface ImageDownDelegate : NSObject
///
/////
@end
 
@interface UIImageView (URLImage)
 
@property(nonatomic,strong)ImageDownDelegate* callback;
-(void) setImageWithUrl:(NSString*)url imgName:(NSString*)imgName progress:(void(^)(int progress, NSError* error)) progress;
 
@end

 ImageDownDelegate 是负责数据下载的接口。
setImageWithUrl的progress,表示使用BLOCK函数块的方式显示下载进度。
参数imgName的意思占位图片,当网络图片正在下载的时候,
用一个本地图片来暂时代替展现。
 
ImageDownDelegate私有属性如下:
 
typedef void (^FUNC)(int progress,  NSError* error);         这个就是setImageWithUrl提供的下载进度回调函数
typedef void (^FUNC2)(NSData* data, NSError* error);     这个是完成回调函数
@interface ImageDownDelegate()
/////
@property(copy) FUNC func;
@property(copy) FUNC2 completion;
@property(nonatomic)UIImageView* imageView;   当下载完成后,设置这个图片控件的Image,让网络图片展示出来
@property(nonatomic)UIButton* imageButton;  这个是UIButton的情况下,下载完网络图片之后展示UIButton的背景。
@property(nonatomic,strong)NSMutableData* data; 这个是下载的图片数据内容,在didReceiveData 组合所有下载的数据。
@property(nonatomic) long long total_length; 图片数据的总长度,在 didReceiveResponse计算得知
@property(nonatomic) long long curr_length;当前下载的数据长度,在 didReceiveData 计算得知
 
@end
 
ImageDownDelegate 接口实现如下主要几个方法:
 
////这个方法是从网络获取 HTTP回答头信息,从这里可以知道下载的图片长度,因此记录下来,作为下载进度的依据。
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
/////真正的数据接收回调函数,在这里应该把接收到的数据组合起来,计算并且调用进度函数,通知下载进度。
 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
 
/////图片数据已经完全下载完成,在这里应该设置UIImageView的Image,这个时候,图片就可以展现出来。
 -(void)connectionDidFinishLoading:(NSURLConnection *)connection;
 
///////下载过程中出现错误,这里应该通知失败。
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
 
 
可以看到 UIImageView (URLImage) 里有个 callback属性, 但是类别类不允许有属性存在,因此采用
objc_setAssociatedObject, objc_getAssociatedObject函数来解决这个问题。
为何需要这个代理类的 callback呢?
因为假设某个UIImageView调用 setImageWithUrl下载某个网络图片,当这个网络图片正在下载过程中,
接着它又调用setImageWithUrl下载另一个网络图片,应该取消第一次的下载,这个callback就起到这个作用。
 
最后看看 setImageWithUrl的大致实现过程:
 
-(void) setImageWithUrl:(NSString*)url imgName:(NSString*)imgName progress:(void(^)(int progress, NSError* error)) progress
{
    ////
    if( self.callback){ ///如果之前有正在下载的数据,则需要移除,否则遇到重新请求网络图片的UIImageView可能出现混乱
        ////这里应该真正取消前一次的图片下载,但是我使用 NSURLProtocol协议缓存数据,所以这里让他继续后台下载并且缓存起来。
        self.callback.imageButton = nil;
        self.callback.imageView = nil;
        ////
     //   NSLog(@"######***** CCOOOOOOOO ");
    }
   
    ///////这里我使用 NSURLProtocol 协议来缓存所有图片数据,这里的意思先判断缓存是否存在这个URL定位的图片,
          如果存在则从缓存获取图片直接显示。
         
    NSString* path = [SimpleURLProtocolCache getCacheFile:url];
    if(path){
        self.image = [UIImage imageWithContentsOfFile:path];
        ////
        return ; //////
    }
    ///////是否显示占位图
    if( imgName ){
        ////
        self.image = [UIImage imageNamed:imgName]; ////
       
        ///////
    }
   
    ////
    NSMutableURLRequest* newRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]
                                              cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                          timeoutInterval:10.0];
   
    ///////
    ImageDownDelegate* cbk = [[ImageDownDelegate alloc] init];
   
    cbk.func = progress;
    cbk.completion = nil;
    cbk.imageView = self;
    cbk.imageButton = nil;
   
   
    self.callback = cbk;  /////////
   
    ////
    if(progress){
        ////
        progress(0, nil); ///
    }
    设置代理,开始图片的真正下载,下载后会同时被 NSURLProtocol 协议缓存。
    NSURLConnection* conn = [NSURLConnection connectionWithRequest:newRequest delegate:cbk];
   
    [conn start];
    ///////
   
}
 图片缓存,我使用扩展 NSURLProtocol协议来缓存所有 NSURL的数据,
你也可以自己实现缓存来缓存图片,相信自己实现这个缓存也不复杂的。


这个接口对应的资源下载地址:

http://download.csdn.net/detail/fanxiushu/8886897



版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

iOS UIImageView显示网络图片的基础用法

先解释下以下代码中的变量: picsURL是一个存储URL地址的数组 choice是选择图片的索引数 self.imageView是View中的UIImageView 其实显示一幅网络上的图片十分简单...

iOS开发tableView的cell里面有textField,键盘出现的时候,自动上移

首先在ios4以后,当UITableViewCell里有UITextfield,当输入时键盘遮盖了UITextField,UITableView是会自动上移,当如果要让tableView自动滚动的话,...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

IOS开发-从网络获取图片并显示

从网络获取图片并显示:let url:NSURL = NSURL(string: "http://obs8l45rh.bkt.clouddn.com/ad_0.jpg")! let data:NSDa...

atop安装和使用

atop就是一款用于监控Linux系统资源与进程的工具,它以一定的频率记录系统的运行状态,所采集的数据包含系统资源(CPU、内存、磁盘和网络)使用情况和进程运行情况,并能以日志文件的方式保存在磁盘中。...
  • atco
  • atco
  • 2016-12-06 12:35
  • 1393

Linux系统与程序监控工具atop教程

引言 Linux以其稳定性,越来越多地被用作服务器的操作系统(当然,有人会较真地说一句:Linux只是操作系统内核:)。但使用了Linux作为底层的操作系统,是否我们就能保证我们的服务做到7*24地...
  • bytxl
  • bytxl
  • 2015-08-06 14:32
  • 541

atop就是一款用于监控Linux系统资源与进程的工具

引言 Linux以其稳定性,越来越多地被用作服务器的操作系统(当然,有人会较真地说一句:Linux只是操作系统内核:)。但使用了Linux作为底层的操作系统,是否我们就能保证我们的服务做到7*2...

atop监控linux性能

首先,atop是一个强大的工具。当我们为linux自豪的时候,也要留意linux的性能,使用了Linux作为底层的操作系统,是否我们就能保证我们的服务做到7*24地稳定呢?答案是否定的。要知道业务功能...

性能测试之观测---Atop

无论iozone还是netperf都可以通过atop来观察他们的性能。 Atop介绍:          atop是一个高级的Linux系统全屏性能监视器,会定期的显示CPU、内存、磁盘、网络的负...

进程查看工具htop和atop

进程查看工具htop和atop htop工具 htop是一个类似top的交互式进程查看工具,但是可以垂直和水平滚动来查看所有进程和他们的命令行。进程的相关操作(killing,renicing)不...

centos性能监控系列三:监控工具atop详解

引言 Linux以其稳定性,越来越多地被用作服务器的操作系统(当然,有人会较真地说一句:Linux只是操作系统内核:)。但使用了Linux作为底层的操作系统,是否我们就能保证我们的服务做到7*24地...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)