SDWebImage 源码阅读(一)

【iOS】SDWebImage源码学习--未完 SDWebImage是一个流行的第三方库,用于在iOS和macOS应用程序中异步下载和缓存图像。 阅读详情

1. 前言

一直没有系统的阅读过整套源码,仅仅是看过几篇总结的文章,了解了设计思路,年前项目刚结束,终于有大块时间仔细阅读一下 SDWebImage 框架了。开始阅读的时候感觉很简单,也没有添加自己的注释,最后越看越乱,发现很多细节处理和逻辑完整性和我之前自己思考的不太一样,就这样乱糟糟的看了一下午,感觉这样通读的效果不是很好。今天换了一种思维来理解,看别人的源码和做英语阅读一样,先笼统的浏览一遍,然后带着问题阅读,效果特别好。简单看了一遍,记录一下学习笔记。

2. 概况

首先看 UIImageView+WebCache 这个扩展类,给 imageView 添加图片的方法一共有以下几种:

- (void)sd_setImageWithURL:(NSURL *)url;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;

- (void)sd_setImageWithURL:(NSURL *)url completed:(SDWebImageCompletionBlock)completedBlock;

- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;

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

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

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

以上方法最后都会调用下面的方法:

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

也就可以确定,这个方法就是我们阅读源码的入口了。大概知道这些参数都是什么意思:

  • url 和 placeholder 不用再介绍了

  • SDWebImageOptions 应该是枚举,进入所在类查看,是位掩码,每个字段含义不明确,后面再分析

typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
    ...
};
  • SDWebImageDownloaderProgressBlock 表示正在下载的时候所要处理的事情

  • SDWebImageCompletionBlock 表示下载完成后所要做的事

3. 详解

接下来看看方法里面的具体实现:

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

    // 先将原来的 operation 停止(详情见 3.1)
    [self sd_cancelCurrentImageLoad];

    // 给 imageView 关联要下载的图片的url
    objc_setAssociatedObject(self, &imageURLKey, url, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

    // SDWebImageDelayPlaceholder : 占位图延迟加载标识
    // 默认情况下,占位图先赋值给imageView,然后加载图像。这个标志是图像加载完毕之前占位图不先赋值给imageVIew。

    // 在没有发送请求获取网络端图片之前、如果 options 不等于 SDWebImageDelayPlaceholder
    if (!(options & SDWebImageDelayPlaceholder)) {

        // 刚看到这里懵逼了一下,印象中没有 dispatch_main_async_safe 这个方法啊,进去发现是一个宏定义,目的是UI相关操作要在主线程,没啥技术点,略过
        dispatch_main_async_safe(^{
            self.image = placeholder;
        });
    }


    // 如果 url 存在
    if (url) {

        // setShowActivityIndicatorView: 暴露在头文件中,设置加载图片的时候是否在 imageView 中央添加菊花
        // showActivityIndicatorView : 是 setShowActivityIndicatorView 的 get 方法、返回 BOOL
        // 此状态是用 runtime 关联到 imageView 上的

        // check if activityView is enabled or not
        // 是否添加菊花
        if ([self showActivityIndicatorView]) {

            // 添加菊花
            [self addActivityIndicator];
        }

        __weak __typeof(self)wself = self;
        // 下载图片(详情见 3.2)
        id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {

            // 图片加载完成、移除菊花
            [wself removeActivityIndicator];

            if (!wself) return;

            dispatch_main_sync_safe(^{
                if (!wself) return;

                // SDWebImageAvoidAutoSetImage : 不允许自动将 image 添加到 imageView
                // 默认情况下,图像下载后直接添加到 imageView,但是在某些情况下,我们希望在设置图像之前先有交互(例如应用滤镜或添加交叉淡入淡出动画),如果要在成功完成时手动设置图像,请使用此标志.

                // 如果图片下载成功 并且 (options = SDWebImageAvoidAutoSetImage)
                // 这个就是我之前常用的方法,获得 image 再赋予 button,现在才发现有 UIButton+WebCache 扩展类
                if (image && (options & SDWebImageAvoidAutoSetImage) && completedBlock)
                {
                    // 直接返回 image,不添加到 imagView
                    completedBlock(image, error, cacheType, url);
                    return;
                }
                else if (image) {

                    // 如果image获取成功,直接添加 image 到 imageView
                    wself.image = image;
                    [wself setNeedsLayout];
                } else {

                    // 如果 image获取失败,并且 (options = SDWebImageDelayPlaceholder),才将 placeholder 添加到 imageView,赤裸裸的备胎
                    if ((options & SDWebImageDelayPlaceholder)) {
                        wself.image = placeholder;
                        [wself setNeedsLayout];
                    }
                }
                if (completedBlock && finished) {
                    completedBlock(image, error, cacheType, url);
                }
            });
        }];

        // 将正在下载的 operation 添加到 operation 字典中(详情见 3.3)
        [self sd_setImageLoadOperation:operation forKey:@"UIImageViewImageLoad"];

    } else {  // 如果 url 为空,则抛出错误
        dispatch_main_async_safe(^{

            // 移除菊花
            [self removeActivityIndicator];

            if (completedBlock) {
                NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"Trying to load a nil url"}];
                completedBlock(nil, error, SDImageCacheTypeNone, url);
            }
        });
    }
}
3.1. 将原来的 operation 停止

如果刚刚已经请求了图片,当 imageView 再次加载图片之前,需要取消之前的请求。

进入 sd_cancelCurrentImageLoad 方法

- (void)sd_cancelCurrentImageLoad {
    [self sd_cancelImageLoadOperationWithKey:@"UIImageViewImageLoad"];
}

再进入 sd_cancelImageLoadOperationWithKey: 方法

- (void)sd_cancelImageLoadOperationWithKey:(NSString *)key {
    // Cancel in progress downloader from queue
    // 取消正在进行的下载队列

    // 获取正在下载的队列
    NSMutableDictionary *operationDictionary = [self operationDictionary];

    // 获取 @"UIImageViewImageLoad" 对应的 value
    id operations = [operationDictionary objectForKey:key];
    if (operations) {
        // 如果 value 是数组类型
        if ([operations isKindOfClass:[NSArray class]]) {
            for (id <SDWebImageOperation> operation in operations) {
                // 如果任务存在,则取消任务
                if (operation) {
                    [operation cancel];
                }
            }
        } else if ([operations conformsToProtocol:@protocol(SDWebImageOperation)]){  // 如果符合协议
            [(id<SDWebImageOperation>) operations cancel];
        }

        // 最后移除key对应的value
        [operationDictionary removeObjectForKey:key];
    }
}

代码很容易理解,先获取到 operation 的序列,即 [self operationDictionary]。然后根据 key 索引到对应的 operation,如果 operation 存在,就要取消该 operation。这里需要注意的地方就是,索引到的 operation 其实是一组 operation 集合,那么久需要遍历一个个取消序列中的 operation。最后移除 key 对应的 object。

这里有个疑惑:为啥 operation 都是 id ?而且进入 SDWebImageOperation 后发现只有一个 cancel 方法。为什么这样设计,还有待进一步研究。

3.2. 下载图片
id <SDWebImageOperation> operation = [SDWebImageManager.sharedManager downloadImageWithURL:url options:options progress:progressBlock completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
    ...            
}];

进入后发现这是 SDWebImageManager 的方法,这就是我们继续探索源码核心的下一个入口,这里不做过多介绍,我们将在下一篇中重点介绍。

3.3. 添加新的operation 到队列

进入 sd_setImageLoadOperation: forKey: 方法

- (void)sd_setImageLoadOperation:(id)operation forKey:(NSString *)key {

    // 取消正在进行的下载队列
    [self sd_cancelImageLoadOperationWithKey:key];

    NSMutableDictionary *operationDictionary = [self operationDictionary];
    [operationDictionary setObject:operation forKey:key];
}

看到方法内的实现,就感觉没有什么难度了,sd_cancelImageLoadOperationWithKey: 方法在 3.1 中介绍了,接下来将该 operation 添加到下载队列中。

4. 总结

到此为止,这个类中主要的方法、属性都解析出来了。其他的比如运用 runtime 关联属性等等就不一一介绍了,都比较简单。这个扩展类其实没有太多核心思想,主要就是设计了严密的判断,保证运用该框架的其他开发者能够在各种环境下请求图片。遗留问题就是 SDWebImageManager 下载图片方法内的实现,我们将在下一篇着重介绍。

SDWebImage 源码解析 github 地址:https://github.com/Mayan29/SDWebImageAnalysis

豆包平台原素材下载技术解析:从浏览器插件原理到安全实践 在数字内容处理领域,媒体文件获取与处理是常见需求,其核心原理涉及网络请求拦截与资源解析技术。通过分析网页前端代码和网络流量,可以定位到平台转码后的高质量媒体文件地址,这一过程体现了现代Web技术中资源加载与反爬机制之间的博弈。从技术价值看,掌握该方法不仅能满足个人对特定素材的合理使用需求,还能深化对CDN分发、视频编码格式(如HLS/m3u8流媒体)等基础架构的理解。在实际应用场景中,用户常面临平台水印、动态加载内容等挑战,需借助浏览器开发者工具或专门插件进行应对。本文聚焦豆包平台,探讨如何通过安全可靠的浏 阅读详情

相关推荐

音视频从入门到精通——指数哥伦布码原理

在计算机中,一般数字的编码都为二进制,但是由于以相等长度来记录不同数字,因此会出现很多的。

mirana的专栏 1380

[iOS]SDWebImage 源码阅读(一)

这是我看的第四份比较著名的源码了,看了不只一遍,因为里面蕴含的知识太多了,而且刚开始也有一些地方不懂,不过经过不断的查资料等等终于是差不多理解了,下面就把我看的地方记录下来,希望能对正在看这份代码的人有所帮助,我会尽量的每一处地方都讲到。老规矩,按照一次代码调用的全程来分析。 首先看最常用的方法 /** * Set the imageView `image` with an `url`.

wcxdell的专栏 589

YonSuite如何新增用户并分配角色角色授权图文教程

用友YonSuite产品基础教学

ct341688的博客 617

【原】SDWebImage源码阅读(一)

【原】SDWebImage源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 一直没有系统地读过整套源码,就感觉像一直看零碎的知识点,没有系统读过一本专业经典书籍一样,会有点发虚,感觉知识体系不健全!废话少说,这次我决定好好阅读下SDWebImage的源码,我的阅读方式,是带着问题去阅读源码,然后强迫自己写博客。 2. SDWebIma...

weixin_30706691的博客 128

【雷达】一维和二维自适应波束形成(DBF))DBF附matlab代码

1 简介 数字波束形成技术是天线波束形成原理与数字信号处理技术相结合的产物,其广泛应用于阵列信号处理领域.由于电磁工作环境的恶化和大量射频干扰的存在,在极低的信干噪比(SINR)条件下进行目标检测和信息提取十分困难.对于阵列系统,往往采用自适应数字波束形成(ADBF)技术,来抑制强干扰和方向性干扰对有用信号的影响.介绍了数字波束形成器的基本原理及其DSP的实现结构.​ 2 完整代码 clc;clear all;close all;%%%%%%%%%%%%%%%%%一维DBF%%%%%%%%%%%%%

qq_59747472的博客 7265

PINN求解PDE

PINN求解Dirichlet泊松方程 泊松方程引入 −Δu=f,x∈Ω=(0,1)2-\Delta u=f,x \in \Omega=(0,1)^2−Δu=f,x∈Ω=(0,1)2 u=g,x∈∂Ωu=g,x \in \partial \Omegau=g,x∈∂Ω import torch import time import numpy as np import matplotlib.pyplot as plt import torch.nn as nn def UU(X, order,prob):

forrestguang的博客 3804

SDWebImage源码阅读(一)SDWebImageCompat

  SDWebImageCompat 是SDWebImage 的配置文件,里面利用条件编译对Apple 的各个平台进行了兼容。可以看到SDWebImage 支持当前的MAC/iOS/TV/WATCH 平台。   对各个平台的兼容性对框架开发意义重大。当前我们只是针对iOS 平台进行阅读理解,但是我们应该知道,当我们在别的Apple 的平台开发时,我们依然可以亲切并熟练的使用SDWebImage。...

weixin_30732825的博客 192

【AI智能体】Spring AI Tool 从使用到实战详解

Spring AI Tool

congge 5864

SDWebImage 源码阅读笔记(一)

简介 Asynchronous image downloader with cache support as a UIImageView category. 言简意赅:SDWebImage 以 UIImageView category(分类)的形式,来支持图片的异步下载与缓存。 其提供了以下功能: 以 UIImageView 的分类,来支持网络图片的加载与缓存管理一个异步的图片

冷小G的技术博客 373

现代软件开发技术 | 第1章:Spring基础

Spring是一个轻量级Java 开发框架,最早由Rod Johnson创建,目的是为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题。

知识库搭建ing 454

Python 爬虫实战:爬取股票数据做 K 线图可视化

摘要:本文介绍基于Python的股票数据爬取与K线图可视化全流程技术方案。通过Requests库抓取东方财富网股票数据,使用Pandas进行清洗处理,并利用mplfinance库实现专业K线图绘制。文章详细讲解了数据爬取接口分析、反爬策略配置、K线图绘制方法(包含基础K线图和带均线的进阶版本),以及核心统计指标计算。该方案可应用于股票价格趋势分析,为投资决策提供数据支持,同时强调了数据使用的合规性和技术优化方向。

2503_91057718的博客 2045

SDWebImage3.7.5源码阅读一

0. 图片的异步下载 比如在tableview中: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString* cellID = @"cellID"; UITableViewCell* cell = ...

depaoweng2915的博客 126

【UVM实战】第七章:UVM中的寄存器模型(1)寄存器模型简介

寄存器模型简介~

悟已往之不谏 知来者之可追 2070

IOS SDWebImage 2.X源码阅读(一)

前言: IOS SDWebImage 2.X源码阅读(一) IOS SDWebImage 2.X源码阅读(二) IOS SDWebImage 2.X源码阅读(三) IOS SDWebImage 2.X源码阅读(四) (一)、SDWebImage 的使用 1、我们在项目中使用SDWebImage加载图片,用的最多的方法是UIImageView的category中的...

夏天的风轻轻吹过~~ 519

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

源码阅读:SDWebImage(一)——从使用入手

该文章阅读的SDWebImage的版本为4.3.3。 1.日常使用 在日常的使用中,通常是加载网络图片到UIImageView上展示,所以一般在需要使用SDWebImage的文件中只引用#import "UIImageView+WebCache.h"头文件。 最简单的加载方式是只加载图片地址: UIImageView *imageView = [[UIImageView alloc] initWi...

weixin_34219944的博客 204

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

源码阅读:SDWebImage

SDWebImage是一个开源的iOS第三方库,主要用于下载并缓存网络图片,在我的博文iOS网络资源缓存ZCLURLCache·上篇提到过SDWebImage。它提供了UIImageView、MKAnnotationView、UIButton的categories(分类),支持网络图片的加载与缓存,其中UIImageView应该是使用最广泛的。本文从源码的角度讨论SDWebImage的下载和缓存的实现。

張行之的专栏 837

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

【iOS】SDWebImage源码阅读笔记

最近基本已经将项目完结,这个月开始专心学习源码,将会陆续学习SDWebImage,AFNetworking以及JsonModel的源码由此我们总结一下SDWebImage的调用流程首先我们会进入方法中,然后进入sd-InternalmageWithURL方法中,在这个方法中我们首先通过取消正在运行的任务,任务是通过方法取消的,这一步是为了避免同一资源被重复下载,接着我们初始化(这里因为是单例,所以只初始化一次),接着进行一系列配置后调用方法,首先检查URL是否在错误的集合中,如果没有就调用。

weixin_72437555的博客 1199

SDWebImage源码解析

一、准备知识 在正式学习源码前,先讲一些SDWebImage中用到的生僻知识点,有些用的很频繁,但是很多人对这些知识点模糊不清,如果不搞清楚会大大影响阅读效率,比如枚举NS_OPTIONS的二进制位运算。 1. NS_OPTIONS与位运算 NS_OPTIONS用来定义位移相关操作的枚举值,当一个枚举变量需要携带多种值的时候就需要,我们可以参考UIKit.Framework的头文件,可以看到大量的...

阿飞小伙子_博客 660

SDWebImage源码分析

源码阅读目的古语说的好“读书破万卷,下笔犹如神”,源码阅读就是一个挖掘别人思路,获取他人精华的一个途径。源码阅读就是站在别人的肩膀上,让自己看的更远。源码阅读对于提高coder的技术水平是非常重要的一个过程。“取其精华,去其糟粕”。所以需要读一些经典的源码,提高自身的实力。世人都说阅读源代码对于功力的提升是十分显著的。 源码主要功能基本概述SDWebImage的作用是实现对网络图片的异步下载以及提供

coder的专栏 1873

源码阅读:SDWebImage(四)——SDWebImageCoder

该文章阅读的SDWebImage的版本为4.3.3。 这个类定义了两个协议,目的是定义图片编解码类所要实现的接口。 1.公共变量与函数 /** 定义了一个BOOL类型的key,用于定义是否在解压缩期间缩放图片 */ FOUNDATION_EXPORT NSString * _Nonnull const SDWebImageCoderScaleDownLargeImagesKey; 复制代码NS...

weixin_34128501的博客 299

[iOS]-SDWebImage实现机制及源码分析

SDWebImage的主要功能以及一些知识点 提供UIImageView的一个分类,以支持网络图片的加载和缓存管理 其是一个异步的图片加载器 一个异步的内存+磁盘图片缓存 支持GIF图片 支持WebP图片(WebP图像格式是新的图像压缩格式) 后台图片解压缩处理 确保同一个URL图片不被下载多次以及确保虚假的URL不会被反复加载 确保下载及缓存时,主线程不被阻塞 结构 (设计思路借鉴:提供多种接口,到底层调用到同一个方法,减少调用方对可选参数的传递): UIImageView+WebCache和UIBu

m0_52192682的博客 1926

SDWebImage 源码分析

SDWebImage 源码分析 首先我 fork 了 SDWebImage 的源码,见 conintet/SDWebImage,这样在本文的链接中都是链到我的 fork 中,这么做的目的是防止将来 SDWebImage 代码发生变化导致本文的链接不准确。 有关 SD (SDWebImage 简称为 SD) 的使用方式还是得参考其 README 或者 wiki。本文只是阅读其源码的笔记。 图片下载 ...

weixin_33858249的博客 115

SDWebImage 源码阅读笔记

转载自Cocoa China,原文地址:http://www.cocoachina.com/ios/20170511/19252.html 前不久做了一个生成快照的需求,其中用到 SDWebImage 来下载图片,在使用该框架的过程中也遇到了一些问题,索性正好就把 SDWebImage (v3.7.3) 源码细读了一下,学习一下其中的设计思想和技术点,为了梳理思路,顺便写下了这篇

Secret Island 1102

SDWebImage源码阅读

前言 SDWebImage强大的网络图片加载库,以前只是能够灵活使用,对底层的实现原理,也是知其然而不知其所以然,但是成为一名优秀的开发者来说,会用只是最简单的一步,更重要的是要研究其底层的技术实现和设计思路原理。这个月工作也不忙,所以阅读下类库源码。记录下自己的思考与总结。 SDWebImage 简介 提供UIImageView的一个分类,用来加载网络图片并且对网络图片的缓存进

iOS&Android开发 494
上一篇: 零耦合仿百度外卖波浪动画
下一篇: SDWebImage 源码阅读(二)
mayan29
博客等级 码龄11年 13粉丝 24原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值