一 SDWebImage下载图片的基本操作
1 下载图片并显示(内存缓存&磁盘缓存)
[self.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://img3.a0bi.com/upload/ttq/20150125/1422148697268_middle.jpg"] placeholderImage:[UIImage imageNamed:@"Snip20160112_4"]];
2 下载图片显示并计算下载进度
2.1 代码实现内存缓存,磁盘缓存和下载进度
- (void)download
{
[self.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://i.ce.cn/fashion/news/201603/04/W020160304475595612586.jpg"] placeholderImage:[UIImage imageNamed:@"/Users/xiaofeng/Desktop/Snip20160316_1.png"] options:SDWebImageLowPriority | SDWebImageCacheMemoryOnly progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"%f",(float)receivedSize / expectedSize);
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"%@---%@",error,[NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES) lastObject]);
switch (cacheType) {
case SDImageCacheTypeNone:
NSLog(@"直接下载的图片-----");
break;
case SDImageCacheTypeDisk:
NSLog(@"磁盘缓存图片-----");
break;
case SDImageCacheTypeMemory:
NSLog(@"内存缓存图片-----");
break;
default:
break;
}
}];
}
3 下载图片不显示并且监听下载进度(用框架中的管理者模块)
3.1 代码实现内存缓存,磁盘缓存和下载进度
- (void)download2
{
[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:@"http://img3.a0bi.com/upload/ttq/20150125/1422148697268_middle.jpg"] options:kNilOptions progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"%f",(float)receivedSize / expectedSize);
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
NSLog(@"%@-----%@",error,[NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES) lastObject]);
if (error == nil) {
self.imageView.image = image;
}
}];
}
4 下载图片不显示并且不做任何的处理
4.1 注意:完成后回调是在子线程中处理的,刷新UI显示图片是在主线程中进行的
- (void)download3
{
[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:@"http://image.zjg.js.cn/upload/editor/2014-7-1/2014711345189400th1b.jpg"] options:SDWebImageDownloaderLowPriority progress:^(NSInteger receivedSize, NSInteger expectedSize) {
NSLog(@"%f",(float)receivedSize / expectedSize);
NSLog(@"1-------%@",[NSThread currentThread]);
} completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {
NSLog(@"2-------%@",[NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"3--------%@",[NSThread currentThread]);
self.imageView.image = image;
});
}];
}
5 播放Gif图片
- (void)download5
{
NSURL *url = [NSURL URLWithString:@"http://img4q.duitang.com/uploads/item/201501/26/20150126180214_mAmSH.thumb.224_0.gif"];
NSData *data = [NSData dataWithContentsOfURL:url];
self.imageView.image = [UIImage sd_animatedGIFWithData:data];
}
6 接收到内存发出来的警告,如何处理?
6.1 取消当前正在进行的所有的下载操作
[[SDWebImageManager sharedManager] cancelAll];
6.2 清除缓存数据
[[SDWebImageManager sharedManager].imageCache cleanDisk];
[[SDWebImageManager sharedManager].imageCache clearMemory];
6.2.1 两者清除区别:
1> cleanDisk:删除过期的文件数据,计算当前未过期的已经下载的文件数据的大小,如果发现该数据大小大于我们设置的最大缓存数据大小,那么程序内部会按照按文件数据缓存的时间从远到近删除,知道小于最大缓存数据为止。
2> clearMemory:直接删除文件,重新创建新的文件夹
7 SDWebImage框架内部的具体实现细节
7.1 判断当前图片类型:只判断图片二进制数据的第一个字节
7.2 默认的缓存周期:1周
7.3 缓存策略:默认情况下既做内存缓存又做磁盘缓存,下载图片前先检查内存缓存,再检查磁盘缓存
7.4 缓存的实现方式:采用了苹果推出的专门用来处理缓存的类NSCache
7.5 框架内部允许的最大并发数:6
7.6 对系统内存警告的处理方式:框架内部监听系统内存警告的通知,当发生后移除内存缓存中的所有对象
7.7 下载队列中对多个图片任务的处理方式:提供了FIFO和LIFO两种方式,默认为FIFO
7.8 如何下载图片:采用NSURLConnection发送网络请求,在其代理方法中接收数据并处理进度回调等工作
7.9 请求超时的设定:15秒
7.10 磁盘缓存图片的命名:以该图片的URL进行MD5散列加密【echo -n “url” |MD5】
7.11 缓存路径:~/Library/Caches/default/com.hackemist.SDWebImageCache.default
7.12 key—–>URL(如何优化):用黑名单(当一个URL请求失败后,会被添加到黑名单,可以有效的防止一个错误的URL被多次尝试下载)
二 RunLoop基本使用
1 RunLoop字面意思:跑圈
2 RunLoop实际含义:一个APP能一直运行的关键
3 注意:
(1)如果没有RunLoop,那么程序一启动就会退出,什么事情都做不了。
(2)如果有了RunLoop,那么相当于在内部有一个死循环,能够保证程序的持续运行
(3)main函数中的RunLoop
——a 在UIApplication函数内部就启动了一个RunLoop,该函数返回一个int类型的值
——b 这个默认启动的RunLoop是跟主线程相关联的
4 RunLoop与线程的关系
(1)RunLoop和线程的关系:一个RunLoop对应着一条唯一的线程
——问题:如何让子线程不死
——回答:给这条子线程开启一个RunLoop
(2)RunLoop的创建:主线程RunLoop已经创建好了,子线程的RunLoop需要手动创建
(3)RunLoop的生命周期:在第一次获取时创建,在线程结束时销毁
三 获取RunLoop对象
1 第一种类型的RunLoop:
1.1 获得当前线程对应的RunLoop
NSRunLoop *run = [NSRunLoop currentRunLoop];
1.2 获取主线程的RunLoop
NSRunLoop *run1 = [NSRunLoop mainRunLoop];
2 第二种类型的RunLoop
2.1 当前的RunLoop
CFRunLoopRef current = CFRunLoopGetCurrent();
2.2 获取主线程对应的RunLoop
CFRunLoopRef main = CFRunLoopGetMain();
3 注意点:
3.1 注意点:开一个子线程创建runloop,不是通过alloc init方法创建,而是直接通过调用currentRunLoop方法来创建,它本身是一个懒加载的。
3.2 在子线程中,如果不主动获取Runloop的话,那么子线程内部是不会创建Runloop的。可以下载CFRunloopRef的源码,搜索_CFRunloopGet0,查看代码。
3.3 Runloop对象是利用字典来进行存储,而且key是对应的线程Value为该线程对应的Runloop。
四 理解三张关于RunLoop的运行图
第一张图:RunLoop的处理逻辑
以上的描述是对第一张图的RunLoop运行描述
第二张图:通俗易懂图
特别说明:两张图其实描述的都差不多,只有第七点做了判断.
第三张图:mode(模式图)
解析第三张图:
注意: Runloop要想跑起来,它的内部必须要有一个mode,这个mode里面必须有source\observer\timer,至少要有其中的一个。
01. CFRunloopModeRef代表着Runloop的运行模式
02. 一个Runloop中可以有多个mode,一个mode里面又可以有多个source\observer\timer等等
03. 每次runloop启动的时候,只能指定一个mode,这个mode被称为该Runloop的当前mode
04. 如果需要切换mode,只能先退出当前Runloop,再重新指定一个mode进入
05. 这样做主要是为了分割不同组的定时器等,让他们相互之间不受影响
06. 系统默认注册了5个mode
—–a. kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
—–c. UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
—–d. GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
—–e. kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode
五 总结
注意: 以上就是对SDWebImage框架和RunLoop的基本使用,还有很多不足的地方,我会找时间补上,大家有什么问题,可以给我留言,谢谢!!!!