代码:https://github.com/xufeng79x/SDWebImage

1.简介

  SDWebImage是一个第三方框架,它能够帮助我们有效管理应用图片下载,沙盒保存和内存保存的任务。通过这篇文章将了解到它的原理和一般使用方式。

2.图片获取

  记得在[New learn] 设计模式文章中我们讨论了通过LibraryAPI类将HTTPClient和PersistencyManager包装起来进行图片的下载,基本原理为:

当本地沙盒中存在对应图片文件时候load本地文件否则回去网上下载并保存在本地以备后续使用。这里我们在增加一个内存缓存,将图片缓存在内存中:

 增加图片缓存:

@interface PersistencyManager () {
    // an array of all albums
    NSMutableArray *albums;

    // 图片缓存
    NSMutableDictionary *imageCache;

}
@end

随后在图片保存以及在图片从沙盒读取的时候讲image信息放入其中,等待下次再去读取相同图片的时候就直接会去缓存中读取。

- (void)saveImage:(UIImage*)image filename:(NSString*)filename
{
    // 进到这里可以认为图片刚从往下下载了
    NSLog(@"Get the image:%@ from internet!", filename);

    // 将图片放到缓存中
    [imageCache setObject:image forKey:filename];
。。。。。。

}

- (UIImage*)getImage:(NSString*)filename
{
    NSString *fileName = filename;
    // 先从缓存中获取数据,如果有就直接返回
    UIImage *image = [imageCache objectForKey:filename];
    if (image) {
        NSLog(@"Get the image:%@ from cache!", filename);
        return image;
    }
。。。。。
    // 当图片在沙盒中,但是没有在缓存中,将图片放到缓存
    if (image)
    {
        NSLog(@"Get the image:%@ from sandbox!", fileName);
        // 将图片放到缓存中
        [imageCache setObject:image forKey:fileName];
    }

    return image;
}

测试

1.获取沙盒路径:

(lldb) po NSHomeDirectory()
/Users/apple/Library/Developer/CoreSimulator/Devices/8E2826AC-C429-4A39-B0EE-C261E155E191/data/Containers/Data/Application/0251E391-F9DD-4BA3-AA81-74D35F9613B5

(lldb) 

2.前往沙盒,删除沙盒中已经存在的图片:

3.运行程序,此时由于缓存和沙盒中并没有图片信息,他将从网络上下载图片。

BlueLibrary[:] Get the image:d000baa1cd11728b0d5fc2bec9fcc3cec3fd2c3f.jpg from internet!
-- :::] Get the image:.jpg from internet!
-- :::] Get the image:.jpg from internet!
-- :::] Get the image:.jpg from internet!
-- :::] Get the image:.jpg from internet!

沙盒文件夹中会生成图:

4.当点击删除按钮的时候,程序会重新load 封面图片,这个时候回从哪里读取图片呢?

-- :::] Get the image:.jpg from cache!
-- :::] Get the image:d000baa1cd11728b0d5fc2bec9fcc3cec3fd2c3f.jpg from cache!
-- :::] Get the image:.jpg from cache!
-- :::] Get the image:.jpg from cache!

可以看到都是从缓存中将图片读取出来,这是由于网络下载图片后会在沙盒生成文件并将在缓存中保存这些图片。

5.当关闭程序,在运行应用的时候,应该会从沙盒中读取,因为缓存中由于重启的原因不会有数据。

-- :::] Get the image:.jpg from sandbox!
-- :::] Get the image:d000baa1cd11728b0d5fc2bec9fcc3cec3fd2c3f.jpg from sandbox!
-- :::] Get the image:.jpg from sandbox!
-- :::] Get the image:.jpg from sandbox!
-- :::] Get the image:.jpg from sandbox!

上述流程总结:

  在这节中我们自己实现了图片的下载,保存和缓存。大致的实现原理如下:

其中在我们的应用中还不会出现多线程操作的重复问题,如果有这个场景,那么我们就需要在新建一个线程缓存区判断下载指定图片的线程是否存在,如果存在就不在进行重复操作。

3.使用框架SDWebImage

上述的过程复杂繁琐,在iOS开发世界中,我们同样可以使用很多第三方框架,SDWebImage框架就是解决我们上述场景的解决方案。

3.1 什么是SDWebImage

官网:https://github.com/rs/SDWebImage

3.2 如何使用

下载框架:进入官网,点击Download ZIP

导入框架:将框架文件夹拷贝到工程中

使用框架:

框架为我们提供丰富的API和属性参数。

直接使用框架方法来代替现有代码:

- (void)downloadImage:(NSNotification*)notification
{

    UIImageView *imageView = notification.userInfo[@"imageView"];
    NSString *coverUrl = notification.userInfo[@"coverUrl"];

  // 框架的词方法的功能已经可以替代注释掉的代码的功能

[imageView sd_setImageWithURL:[NSURL URLWithString:coverUrl] placeholderImage:nil];

//    // 2 从缓存或者沙盒中读取图片
//    imageView.image = [persistencyManager getImage:[coverUrl lastPathComponent]];
//
//    if (imageView.image == nil)
//    {
//        // 3 当缓存或者沙盒中图片不存在的时候,远程多线程下载图片。
//        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//            UIImage *image = [httpClient downloadImage:coverUrl];
//
//            // 4 图片下载完毕后需要在主线程中更行UI,并保存图片到沙盒和刷新缓存
//            dispatch_sync(dispatch_get_main_queue(), ^{
//                imageView.image = image;
//                [persistencyManager saveImage:image filename:[coverUrl lastPathComponent]];
//            });
//        });
//    }
}

将沙盒中的图片文件删除,重启应用。

非常不幸,和我一样遇到了如下的问题吗?
Undefined symbols for architecture x86_64:
  "_CGImageSourceCopyPropertiesAtIndex", referenced from:
      +[UIImage(MultiFormat) sd_imageOrientationFromImageData:] in UIImage+MultiFormat.o
      -[SDWebImageDownloaderOperation connection:didReceiveData:] in SDWebImageDownloaderOperation.o
      +[UIImage(GIF) sd_frameDurationAtIndex:source:] in UIImage+GIF.o
  "_CGImageSourceCreateImageAtIndex", referenced from:
      -[SDWebImageDownloaderOperation connection:didReceiveData:] in SDWebImageDownloaderOperation.o
      +[UIImage(GIF) sd_animatedGIFWithData:] in UIImage+GIF.o
  "_CGImageSourceCreateWithData", referenced from:
      +[UIImage(MultiFormat) sd_imageOrientationFromImageData:] in UIImage+MultiFormat.o
      -[SDWebImageDownloaderOperation connection:didReceiveData:] in SDWebImageDownloaderOperation.o
      +[UIImage(GIF) sd_animatedGIFWithData:] in UIImage+GIF.o
  "_CGImageSourceGetCount", referenced from:
      +[UIImage(GIF) sd_animatedGIFWithData:] in UIImage+GIF.o
  "_OBJC_CLASS_$_MKAnnotationView", referenced from:
      l_OBJC_$_CATEGORY_MKAnnotationView_$_WebCache in MKAnnotationView+WebCache.o
      l_OBJC_$_CATEGORY_MKAnnotationView_$_WebCacheDeprecated in MKAnnotationView+WebCache.o
  "_kCGImagePropertyGIFDelayTime", referenced from:
      +[UIImage(GIF) sd_frameDurationAtIndex:source:] in UIImage+GIF.o
  "_kCGImagePropertyGIFDictionary", referenced from:
      +[UIImage(GIF) sd_frameDurationAtIndex:source:] in UIImage+GIF.o
  "_kCGImagePropertyGIFUnclampedDelayTime", referenced from:
      +[UIImage(GIF) sd_frameDurationAtIndex:source:] in UIImage+GIF.o
  "_kCGImagePropertyOrientation", referenced from:
      +[UIImage(MultiFormat) sd_imageOrientationFromImageData:] in UIImage+MultiFormat.o
      -[SDWebImageDownloaderOperation connection:didReceiveData:] in SDWebImageDownloaderOperation.o
  "_kCGImagePropertyPixelHeight", referenced from:
      -[SDWebImageDownloaderOperation connection:didReceiveData:] in SDWebImageDownloaderOperation.o
  "_kCGImagePropertyPixelWidth", referenced from:
      -[SDWebImageDownloaderOperation connection:didReceiveData:] in SDWebImageDownloaderOperation.o
ld: symbol(s) not found for architecture x86_64
解决方法:发生此问题的原因为框架还依赖于其他框架http://stackoverflow.com/questions/12306161/build-fail-when-using-sdwebimage

验证:

同时在沙盒中发现框架已经将图片存入了特定的文件夹中:

4. SDWebImage再研究:

在测试中我们使用到了一个API方法,通过URL来获取图片的方法内部其实都调用了以下实现方法

/**

 * Set the imageView `image` with an `url`, placeholder and custom options.

 *

 * The download is asynchronous and cached.

 *

 * @param url            The url for the image.

 * @param placeholder    The image to be set initially, until the image request finishes.

 * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.

 * @param progressBlock  A block called while image is downloading

 * @param completedBlock A block called when operation has been completed. This block has no return value

 *                       and takes the requested UIImage as first parameter. In case of error the image parameter

 *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean

 *                       indicating if the image was retrieved from the local cache or from the network.

 *                       The fourth parameter is the original image url.

 */

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;

它能够制定图片占位符号,操作选项(是否缓存图片等),下载中处理和下载后处理块。

除此之外,对于gif图片来说,和调用普通图片并没有任何差别。

原理:

其实此框架的原理和我们前面自己实现的原理是一个道理,它也有缓存,沙盒存储和网络下载三部分。我们可以通过SDImageCache.m定义的如下方法可见一斑:

#if TARGET_OS_IPHONE
        // Subscribe to app events
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(clearMemory)
                                                     name:UIApplicationDidReceiveMemoryWarningNotification
                                                   object:nil];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(cleanDisk)
                                                     name:UIApplicationWillTerminateNotification
                                                   object:nil];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(backgroundCleanDisk)
                                                     name:UIApplicationDidEnterBackgroundNotification
                                                   object:nil];
#endif

详见:https://github.com/rs/SDWebImage

以上。

[New learn]SDWebImage框架的基本使用的更多相关文章

  1. iOS开发——多线程篇——快速生成沙盒目录的路径,多图片下载的原理、SDWebImage框架的简单介绍

    一.快速生成沙盒目录的路径 沙盒目录的各个文件夹功能 - Documents - 需要保存由"应用程序本身"产生的文件或者数据,例如:游戏进度.涂鸦软件的绘图 - 目录中的文件会被 ...

  2. [New learn] UIKit 框架类

    NSObject NSObject is the root class of most Objective-C class hierarchies. NSDataAsset The NSDataAss ...

  3. iOS边练边学--多线程练习的多图片下载 以及 使用第三方框架(SDWebImage)的多图片下载

    一.自己实现多图片下载应该注意的问题 沙盒缓存的问题 程序缓存的问题 cell重复利用显示图片混乱的问题 -- 用户拖拽快,下载图片慢导致的 解决图片混乱引入NSOperation集合的问题 资源下载 ...

  4. AJ学IOS(55)多线程网络之图片下载框架之SDWebImage

    AJ分享,必须精品 效果: 代码: - (NSArray *)apps { if (!_apps) { NSArray *dictArray = [NSArray arrayWithContentsO ...

  5. SDWebImage ReadMe.md文档简单说明

    SDWebImage ReadMe.md 文档 附:SDWebImage框架github下载地址:https://github.com/rs/SDWebImage 注1:该文章简单翻译了SDWebIm ...

  6. 多线程与网络之SDWebImage和NSCache

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  7. 搭建简单的网络部分(OC)框架

    准备工作 1.文件目录结构示图(按照MVC分层) 文件目录结构图/自定义Cell Controller: CYXOneViewController Model: CYXMenu View: CYXCe ...

  8. iOS利用SDWebImage实现缓存的计算与清理

    概述 可以仅仅清理图片缓存, 也可以清理所有的缓存文件(包括图片.视频.音频等). 详细 代码下载:http://www.demodashi.com/demo/10717.html 一般我们项目中的缓 ...

  9. IOS-第三方(SDWebImage)

    SDWebImage ReadMe.md 文档 附:SDWebImage框架github下载地址:https://github.com/rs/SDWebImage注1:该文章简单翻译了SDWebIma ...

随机推荐

  1. Python正则表达式re模块

    re.compile(pattern,flags=0)将正则表达式编译成正则表达式对象.可以使用match()和search()方法进行匹配.对于常用的表达式可以先进行编译,后续可多次使用以提高效率. ...

  2. Android 4.0源码结构

    Android 4.0 |-- Makefile |-- bionic (bionic C库) |-- bootable (启动引导相关代码) |-- build (存放系统编译规则及generic等 ...

  3. BZOJ4889 & 洛谷3759:[TJOI2017]不勤劳的图书管理员——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4889 https://www.luogu.org/problemnew/show/P3759 加里 ...

  4. 洛谷 P4964 绫小路的特别考试 解题报告

    P4964 绫小路的特别考试 题目背景 这世界上「胜利」便是一切.无关乎过程. 要付出多少牺牲都无所谓.只要最后我「胜出」那就行了. 题目描述 一场新的特别考试来临了,这次的考试内容是(wan e d ...

  5. Vue项目搭建过程

    环境搭建:mac+nodejs+npm #安装node.js : $ brew install node #安装vue-cil: $ npm install -g vue-cli 注:官网下载安装no ...

  6. 如何使用impdp导入oracle数据库文件

    1.首先,安装好oracle数据库. 2.使用sqlplus进入sysdba权限,sqlplus "/as sysdba", 例如: 3.创建用户framework,例如: CRE ...

  7. 洛谷P1667/[10.22 模拟赛] 数列 (思维+模拟)

    洛谷P1667 数列 题目描述 给定一个长度是n的数列A,我们称一个数列是完美的,当且仅当对于其任意连续子序列的和都是正的.现在你有一个操作可以改变数列,选择一个区间[X,Y]满足\(A_X +A_{ ...

  8. BZOJ2434: [NOI2011]阿狸的打字机(AC自动机+dfs序+树状数组)

    [NOI2011]阿狸的打字机 题目链接:https://www.luogu.org/problemnew/show/P2414 题目背景 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机. ...

  9. arm-linux-gcc等交叉编译工具的安装

    1.软件安装 步骤1:打开虚拟机,在/usr/local/下创建/usr/local/arm文件夹(一般用户自定义程序放到这里) 步骤2:先将安装包从Windows中弄到linux中去.可以用共享文件 ...

  10. Tomcat7项目迁移到Tomcat8中文乱码问题

    我打算开始使用Tomcat8了,先解决中文乱码问题,在解决其它的问题! 个人推荐:修改server.xml方式 对于SpringMVC报的错误我稍后在补充问题 1.问题描述 Tomcat 7下项目切换 ...