SDWebImage內(nèi)部實(shí)現(xiàn)及其原理

SDWebImage的知名度就不用說了棒厘,github上近10k的star,國內(nèi)外太多的App使用其進(jìn)行圖片加載下隧。簡(jiǎn)單介紹一下奢人,它是一個(gè)圖片框架,支持從網(wǎng)絡(luò)中下載且緩存圖片淆院,并設(shè)置圖片到對(duì)應(yīng)的UIImageView 控件或者 UIButton 控件何乎。使用SDWebImage來管理圖片加載,會(huì)極大地提高我們的開發(fā)效率土辩,從而讓我們更加專注于業(yè)務(wù)邏輯實(shí)現(xiàn)支救。也正是因?yàn)檫@樣,讓我們很多開發(fā)都只會(huì)用SDWebImage拷淘,而忽略了它的內(nèi)部實(shí)現(xiàn)各墨,今天我就給大家介紹一下SDWebImage的內(nèi)部實(shí)現(xiàn)及原理。

一启涯、SDWebImage 概述
SDWebImage是一個(gè)開源的第三方庫贬堵,它提供了UIImageView的一個(gè)分類,以支持從遠(yuǎn)程服務(wù)器下載并緩存圖片的功能结洼。它具有以下功能:
1黎做、提供了一個(gè)UIImageView的 category用來加載網(wǎng)絡(luò)圖片,并對(duì)網(wǎng)絡(luò)圖片的緩存進(jìn)行管理松忍。
2蒸殿、采用異步方式來下載網(wǎng)絡(luò)圖片
3、采用異步方式鸣峭,使用 memory+disk 來緩存網(wǎng)絡(luò)圖片伟桅,自動(dòng)管理緩存。
4叽掘、支持 GIF 動(dòng)畫
5楣铁、支持 WebP 格式
6、同一個(gè) URL 的網(wǎng)絡(luò)圖片不會(huì)被重復(fù)下載
7更扁、失效的 URL 不會(huì)被無限重試
8盖腕、耗時(shí)操作都在子線程,確保不會(huì)阻塞主線程
9浓镜、使用 GCD 和 ARC
10溃列、支持 Arm64

二、SDWebImage 使用
1膛薛、使用 ImageView+WebCache category 來加載 網(wǎng)絡(luò)圖片


UIImageView調(diào)用方法.png

2.听隐、使用Blocks,在 block 中得到圖片下載進(jìn)度和圖片加載完成(下載完成或者讀取緩存)的回調(diào),如果你在圖片加載完成前取消了請(qǐng)求操作哄啄,就不會(huì)收到成功或失敗的回調(diào)


Block方式給UIImageView設(shè)置圖片.png

3雅任、使用SDWebImageManager,SDWebImageManager為UIImageView+WebCache category的實(shí)現(xiàn)提供下載圖片接口风范。
SDWebImageManager下載圖片.png

4、單獨(dú)使用 SDWebImageDownloader 來下載圖片沪么,但是圖片內(nèi)容不會(huì)緩存硼婿。
SDWebImageDownloader下載圖片.png

5、使用 SDImageCache 異步緩存圖片
SDImageCache 同時(shí)緩存到內(nèi)存和磁盤中禽车。


圖片存入內(nèi)存和磁盤.png

SDImageCache 只緩存到內(nèi)存:
圖片只存入內(nèi)存.png

讀取緩存時(shí)可以使用 queryDiskCacheForKey:done: 方法寇漫,圖片緩存的 key 是唯一的,通常就是圖片的 absolute URL殉摔。
讀取緩存.png

6州胳、清除緩存文件
清楚緩存文件.png

7、獲取所有緩存圖片的總大小
獲取緩存圖片總大小.png

8逸月、獲取緩存圖片張數(shù)
獲取緩存圖片張數(shù).png

9陋葡、直接從緩存中提取圖片


從緩存提取圖片.png

10、直接刪除緩存中得圖片
刪除緩存中的圖片.png

11彻采、判斷本地緩存中是否存在網(wǎng)絡(luò)中的圖片
是否存在網(wǎng)絡(luò)圖片.png

在實(shí)際的運(yùn)用中腐缤,我們并不直接使用SDWebImageDownloader類及SDImageCache類來執(zhí)行圖片的下載及緩存。為了方便用戶的使用肛响,SDWebImage提供了SDWebImageManager對(duì)象來管理圖片的下載與緩存岭粤。而且我們經(jīng)常用到的諸如UIImageView+WebCache等控件的分類都是基于SDWebImageManager對(duì)象的。該對(duì)象將一個(gè)下載器SDWebImageDownloader和一個(gè)圖片緩存SDImageCache綁定在一起特笋,并對(duì)外提供兩個(gè)只讀屬性來獲取它們剃浇。

三、實(shí)現(xiàn)原理
1猎物、SDWebImage 流程圖


SDWebImage流程圖.png

2虎囚、核心邏輯
1、UIImageView+WebCache 中最核心的方法 sd_setImageWithURL: placeholderImage: options: progress: completed:蔫磨。給UIImageView設(shè)置圖片淘讥,就是調(diào)用此方法,方法內(nèi)部的具體做以下幾件事:

  • 取消當(dāng)前正在進(jìn)行的加載任務(wù) operation
  • 設(shè)置 placeholder
  • 如果 URL 不為 nil堤如,就通過 SDWebImageManager 單例開啟圖片加載任務(wù) operation蒲列,SDWebImageManager 的圖片加載方法中會(huì)返回一個(gè) SDWebImageCombinedOperation 對(duì)象,這個(gè)對(duì)象包含一個(gè) cacheOperation 和一個(gè) cancelBlock搀罢。


    給UIImageView設(shè)置圖片.png

    a.開始加載之前蝗岖,先取消對(duì)應(yīng)的UIImageView先前的圖片下載操作±浦粒框架將對(duì)應(yīng)的下載操作放在UIView的一個(gè)自定義字典屬性(operationDictionary)中抵赢,取消下載操作第一步也是從這個(gè)UIView的自定義字典屬性(operationDictionary)中取出所有的下載操作,然后依次調(diào)用取消方法,最后將取消的操作從(operationDictionary)字典屬性中移除铅鲤。


    最終取消圖片下載方法.png

    b.移除之前沒用的圖片下載操作之后就創(chuàng)建一個(gè)新的圖片下載操作划提,然后設(shè)置到UIView的一個(gè)自定義字典屬性(operationDictionary)中。創(chuàng)建一個(gè)新的圖片下載操作,框架保存了一個(gè)失效的URL列表彩匕,如果URL失效了就會(huì)被加入這個(gè)列表腔剂,保證不會(huì)重復(fù)多次請(qǐng)求失效的URL媒区。根據(jù)給定的URL生成一個(gè)唯一的Key,之后利用這個(gè)key到緩存中查找對(duì)應(yīng)的圖片緩存驼仪。
    圖片下載操作.png

    c.讀取圖片緩存,先拿圖片緩存的 key去內(nèi)存中讀取緩存,如果有袜漩,就返回給 SDWebImageManager 绪爸;如果內(nèi)存沒有緩存,就開啟異步線程去磁盤開始讀取宙攻,如果有就從磁盤同步到內(nèi)存中去奠货,再返回給SDWebImageManager 。如果內(nèi)存和磁盤中都沒有座掘,SDWebImageManager 就會(huì)調(diào)用 downloadImageWithURL: options: progress: completed: 方法去下載递惋。


    讀取圖片緩存.png

    d.在圖片下載方法中,調(diào)用了一個(gè)方法用于添加創(chuàng)建和下載過程中的各類Block回調(diào)溢陪。
    下載狀態(tài)回調(diào)Block.png

    e.如果該URL是第一次加載的話萍虽,那么就會(huì)執(zhí)行createCallback這個(gè)回調(diào)Block,然后在createCallback里面開始構(gòu)建網(wǎng)絡(luò)請(qǐng)求,創(chuàng)建一個(gè) NSMutableURLRequest 對(duì)象和一個(gè) SDWebImageDownloaderOperation 對(duì)象形真,并將該 SDWebImageDownloaderOperation 對(duì)象添加到 SDWebImageDownloader 的downloadQueue 來啟動(dòng)異步下載任務(wù)杉编,在下載過程中執(zhí)行各類進(jìn)度Block回調(diào)。
    第一次加載時(shí)構(gòu)建請(qǐng)求.png

    f.當(dāng)圖片下載完成之后會(huì)回到done的Block回調(diào)中做圖片轉(zhuǎn)換處理和緩存操作咆霜。
    下載完成的回調(diào).png

    g.回到UIImageView控件的設(shè)置圖片方法Block回調(diào)中邓馒,給對(duì)應(yīng)的UIImageView設(shè)置圖片,操作流程到此完成蛾坯。
    設(shè)置圖片.png

3光酣、實(shí)現(xiàn)細(xì)節(jié)
SDWebImage 最核心的功能也就是以下 4 件事:

  • 下載(SDWebImageDownloader)
  • 緩存(SDImageCache)
  • 將緩存和下載的功能組合起來(SDWebImageManager)
  • 封裝成 UIImageView 等類的分類方法(UIImageView+WebCache 等)

3.1 SDWebImageDownloader
3.1.1 SDWebImageDownloader 繼承于 NSObject,主要承擔(dān)了異步下載圖片和優(yōu)化圖片加載的任務(wù)脉课。
SDWebImageDownloader 通過+initialize 和 -init 這兩個(gè)方法實(shí)現(xiàn)注冊(cè)通知和做一些初始化設(shè)置以及默認(rèn)設(shè)置挂疆。SDWebImageDownloader包括設(shè)置最大并發(fā)數(shù)(6)、下載超時(shí)時(shí)長(zhǎng)(15s)等下翎。
SDWebImageDownloader這個(gè)類里面除了這兩個(gè)方法缤言,最核心的方法就是downloadImageWithURL:options: progress: completed:方法,這個(gè)方法中首先調(diào)用 -addProgressCallback: andCompletedBlock: forURL: createCallback: 方法來保存每個(gè) url 對(duì)應(yīng)的回調(diào) block视事,-addProgressCallback 方法會(huì)先進(jìn)行錯(cuò)誤檢查胆萧,判斷 URL 是否為空,如果為 空, 則直接回調(diào) completedBlock跌穗,返回失敗的結(jié)果订晌,然后 return,否則將 URL 對(duì)應(yīng)的 progressBlock 和 completedBlock 保存到 URLCallbacks 屬性中去蚌吸。

有個(gè)細(xì)節(jié)要注意锈拨,因?yàn)榭赡芡瑫r(shí)下載多張圖片,所以就可能出現(xiàn)多個(gè)線程同時(shí)訪問 URLCallbacks 屬性的情況羹唠。為了保證線程安全奕枢,所以這里使用了 dispatch_barrier_sync 來分步執(zhí)行添加到 barrierQueue 中的任務(wù),這樣就能保證同一時(shí)間只有一個(gè)線程能對(duì) URLCallbacks 進(jìn)行操作佩微。
(dispatch_barrier_sync 將某個(gè)任務(wù)插入某個(gè)隊(duì)列中執(zhí)行:想了解的可以看看這篇文章 https://blog.csdn.net/u013046795/article/details/47057585

如果這個(gè) URL 是第一次被下載缝彬,就要回調(diào) createCallback,createCallback 主要做的就是創(chuàng)建并開啟下載任務(wù)哺眯,下面是 createCallback 的具體實(shí)現(xiàn)邏輯:
1.創(chuàng)建一個(gè) NSMutableURLRequest 對(duì)象和一個(gè) SDWebImageDownloaderOperation 對(duì)象谷浅,并將該 SDWebImageDownloaderOperation 對(duì)象添加到 SDWebImageDownloader 的downloadQueue 來啟動(dòng)異步下載任務(wù)。
2.SDWebImageDownloaderOperation 中有3個(gè)block回調(diào)奶卓,分別是progressBlock(接收到的數(shù)據(jù)大小和預(yù)計(jì)數(shù)據(jù)大小)一疯,completedBlock(圖片 UIImage,圖片數(shù)據(jù) NSData夺姑,錯(cuò)誤 NSError墩邀,是否結(jié)束 isFinished),cancelBlock(移除 url 對(duì)應(yīng)的所有回調(diào) block)瑟幕;這三個(gè)block都用了weak-strong dance磕蒲,使用 strongSelf 強(qiáng)引用 weakSelf,目的是為了保住 self 不被釋放只盹,然后檢查 self 是否已經(jīng)被釋放(這里為什么先“崩蓖活”后“判空”呢?因?yàn)槿绻扰锌盏脑捴潮埃锌赡芘锌蘸?self 就被釋放了)
(對(duì)weak-strong dance不理解可以看看 http://www.reibang.com/p/4e6153ea2734

  1. 設(shè)置下載完成后是否需要解壓縮
  2. 如果設(shè)置了 username 和 password站削,就給 operation 的下載請(qǐng)求設(shè)置一個(gè) NSURLCredential 身份認(rèn)證
  3. 設(shè)置 operation 的隊(duì)列優(yōu)先級(jí)
  4. 將 operation 加入到隊(duì)列 downloadQueue 中,隊(duì)列(NSOperationQueue)會(huì)自動(dòng)管理 operation 的執(zhí)行
  5. 如果 operation 執(zhí)行順序是先進(jìn)后出孵稽,就設(shè)置 operation 依賴關(guān)系(先加入的依賴于后加入的)绳矩,并記錄最后一個(gè) operation(lastAddedOperation)

3.1.2 SDWebImageDownloaderOperation
當(dāng)創(chuàng)建的 SDWebImageDownloaderOperation 對(duì)象被加入到 downloader 的 downloadQueue 中時(shí)碱璃,該對(duì)象的 -start 方法就會(huì)被自動(dòng)調(diào)用转捕。
-start 方法中首先創(chuàng)建了用來下載圖片數(shù)據(jù)的 NSURLSession胳螟,然后開啟 connection,同時(shí)發(fā)出開始圖片下載的 SDWebImageDownloadStartNotification 通知接校,為了防止非主線程的請(qǐng)求被 kill 掉猛频,這里開啟 runloop 保活,直到請(qǐng)求返回鹿寻。
一張圖片的數(shù)據(jù)下載是由一個(gè) NSConnection 對(duì)象來完成的睦柴,這個(gè)對(duì)象的整個(gè)生命周期(從創(chuàng)建到下載結(jié)束)又是由 SDWebImageDownloaderOperation 來控制的,將 operation 加入到 operation queue 中就可以實(shí)現(xiàn)多張圖片同時(shí)下載了毡熏。
簡(jiǎn)單概括成一句話就是坦敌,NSURLSession 負(fù)責(zé)網(wǎng)絡(luò)請(qǐng)求,NSOperation 負(fù)責(zé)多線程痢法。
(為什么要用runloop :https://blog.ibireme.com/2015/05/18/runloop/

3.2 SDImageCache
3.2.1 SDImageCache 管理著一個(gè)內(nèi)存緩存和磁盤緩存(可選)狱窘,同時(shí)在寫入磁盤緩存時(shí)采取異步執(zhí)行,所以不會(huì)阻塞主線程疯暑,影響用戶體驗(yàn)。為什么需要緩存膘滨?

  • 以空間換時(shí)間铲咨,提升用戶體驗(yàn):加載同一張圖片,讀取緩存是肯定比遠(yuǎn)程下載的速度要快得多的
  • 減少不必要的網(wǎng)絡(luò)請(qǐng)求,提升性能,節(jié)省流量:一般來講,同一張圖片的 URL 是不會(huì)經(jīng)常變化的,所以沒有必要重復(fù)下載统扳。另外倾鲫,現(xiàn)在的手機(jī)存儲(chǔ)空間都比較大磕道,相對(duì)于流量來疯特,緩存占的那點(diǎn)空間算不了什么。

3.2.2 SDImageCache 的內(nèi)存緩存是通過一個(gè)繼承 NSCache 的 AutoPurgeCache 類來實(shí)現(xiàn)的,NSCache 是一個(gè)類似于 NSMutableDictionary 存儲(chǔ) key-value 的容器腾誉,主要有以下幾個(gè)特點(diǎn):

  • 自動(dòng)刪除機(jī)制:當(dāng)系統(tǒng)內(nèi)存緊張時(shí)徘层,NSCache會(huì)自動(dòng)刪除一些緩存對(duì)象
  • 線程安全:從不同線程中對(duì)同一個(gè) NSCache 對(duì)象進(jìn)行增刪改查時(shí)峻呕,不需要加鎖
  • 不同于 NSMutableDictionary,NSCache存儲(chǔ)對(duì)象時(shí)不會(huì)對(duì) key 進(jìn)行 copy 操作

3.2.3 SDImageCache 的磁盤緩存是通過異步操作 NSFileManager 存儲(chǔ)緩存文件到沙盒來實(shí)現(xiàn)的趣效。

3.2.4 磁盤清理
(1).清掃磁盤緩存(clean)和清空磁盤緩存(clear)是兩個(gè)不同的概念瘦癌,清空是刪除整個(gè)緩存目錄,清掃只是刪除部分緩存文件跷敬。
(2).清掃磁盤緩存有兩個(gè)指標(biāo):一是緩存有效期讯私,二是緩存體積最大限制。SDImageCache中的緩存有效期是通過 maxCacheAge 屬性來設(shè)置的西傀,默認(rèn)值是 1 周斤寇,緩存體積最大限制是通過 maxCacheSize 來設(shè)置的,默認(rèn)值為 0拥褂。
一般在應(yīng)用即將終止時(shí)和退到后臺(tái)時(shí)娘锁,都會(huì)調(diào)用 -cleanDiskWithCompletionBlock: 方法來異步清掃緩存,清掃磁盤緩存的邏輯是饺鹃,先遍歷所有緩存文件莫秆,并根據(jù)文件的修改時(shí)間來刪除過期的文件,同時(shí)記錄剩下的文件的屬性和總體積大小尤慰,如果設(shè)置了 maxCacheAge 屬性的話馏锡,接下來就把剩下的文件按修改時(shí)間從小到大排序(最早的排最前面)雷蹂,最后再遍歷這個(gè)文件數(shù)組伟端,一個(gè)一個(gè)刪,直到總體積小于 desiredCacheSize 為止匪煌,也就是 maxCacheSize 的一半责蝠。
(3).清理內(nèi)存緩存,一般在系統(tǒng)拋出內(nèi)存警告的時(shí)候萎庭,SDWebImage會(huì)自動(dòng)調(diào)用清除內(nèi)存緩存方法霜医,等系統(tǒng)拋出內(nèi)存警告可能有點(diǎn)困難,所以可以根據(jù)需求驳规,自己調(diào)用[[SDImageCache sharedImageCache] clearMemory]; 肴敛,不過這個(gè)方法只是清除了SDWebImage的緩存,并沒有清除系統(tǒng)緩存吗购。如果需要清楚系統(tǒng)緩存可以調(diào)用
[[NSURLCache sharedURLCache] removeAllCachedResponses];來實(shí)現(xiàn)医男。

3.3 SDWebImageManager
SDWebImageManager是圖片加載管理器,主要是將下載和緩存兩個(gè)功能結(jié)合起來捻勉,才算是一個(gè)完整的圖片加載器镀梭。
SDWebImageManager 的核心任務(wù)是由 -downloadImageWithURL:options:progress:completed: 方法來實(shí)現(xiàn)的,這個(gè)方法中先會(huì)從 SDImageCache 中讀取緩存踱启,如果有緩存报账,就直接返回緩存研底,如果沒有就通過 SDWebImageDownloader 去下載,下載成功后再保存到緩存中去透罢,然后再回調(diào) completedBlock榜晦。其中 progressBlock 的回調(diào)是直接交給了 SDWebImageDownloader 的 progressBlock 來處理的。
SDWebImageManager 在讀取緩存和下載之前會(huì)創(chuàng)建一個(gè) SDWebImageCombinedOperation 對(duì)象羽圃,這個(gè)對(duì)象是用來管理緩存讀取操作和下載操作的芽隆,SDWebImageCombinedOperation 對(duì)象有 3 個(gè)屬性:

  • cancelled:用來取消當(dāng)前加載任務(wù)的
  • cancelBlock:用來移除當(dāng)前加載任務(wù)和取消下載任務(wù)的
  • cacheOperation:用來取消讀取緩存操作

3.4 UIImageView+WebCache
UIImageView+WebCache就是我們平時(shí)最常用的圖片加載,是通過調(diào)用 UIImageView+WebCache 的 -sd_setImageWithURL:... 系列方法來加載的统屈,UIImageView+WebCache 實(shí)際上是將 SDWebImageManager 封裝了一層胚吁,內(nèi)部針對(duì) UIImageView 做了一些處理,使用起來更方便愁憔、更直接腕扶、更簡(jiǎn)單。

UIImageView+WebCache 的核心邏輯都在 - sd_setImageWithURL:placeholderImage:options:progress:completed: 方法中吨掌,為了防止多個(gè)異步加載任務(wù)同時(shí)存在時(shí)半抱,可能出現(xiàn)互相沖突和干擾,該方法中首先通過調(diào)用 -sd_cancelCurrentImageLoad 方法取消這個(gè) UIImageView 當(dāng)前的下載任務(wù)膜宋,然后設(shè)置了占位圖窿侈,如果 url 不為 nil,接著就調(diào)用 SDWebImageManager 的 -downloadImage... 方法開始加載圖片秋茫,并將這個(gè)加載任務(wù) operation 保存起來史简,用于后面的 cancel 操作。圖片獲取成功后肛著,再重新設(shè)置 imageView 的 image圆兵,并回調(diào) completedBlock。

需要注意的是為了防止多個(gè)異步加載任務(wù)同時(shí)存在時(shí)枢贿,可能出現(xiàn)互相沖突和干擾殉农,每個(gè) UIImageView 的圖片加載任務(wù)都會(huì)保存成一個(gè) Associated Object,方便需要時(shí)取消任務(wù)局荚。這個(gè) Associated Object 的操作是在 UIView+WebCacheOperation 中實(shí)現(xiàn)的超凳,因?yàn)槌?UIImageView 用到圖片加載功能之外,還有 UIButton 等其他類也用到了加載遠(yuǎn)程圖片的功能耀态,所以需要進(jìn)行同樣的處理轮傍,這樣設(shè)計(jì)實(shí)現(xiàn)了代碼的復(fù)用。

四茫陆、遇到的問題

  • 問題 1:使用SDWebImage加載較多圖片時(shí)金麸,會(huì)出現(xiàn)內(nèi)存警告;
    解決方案:定期調(diào)用 [[SDImageCache sharedImageCache] setValue:nil forKey:@"memCache"];
  • 問題 2:圖片刷新問題:SDWebImage 在進(jìn)行緩存時(shí)忽略了所有服務(wù)器返回的 caching control 設(shè)置簿盅,并且在緩存時(shí)沒有做時(shí)間限制挥下,這也就意味著圖片 URL 必須是靜態(tài)的了揍魂,要求服務(wù)器上一個(gè) URL 對(duì)應(yīng)的圖片內(nèi)容不允許更新。但是如果存儲(chǔ)圖片的服務(wù)器不由自己控制棚瘟,也就是說 圖片內(nèi)容更新了现斋,URL 卻沒有更新,這種情況怎么辦偎蘸?
    解決方案:在調(diào)用 sd_setImageWithURL: placeholderImage: options:方法時(shí)設(shè)置 options 參數(shù)為SDWebImageRefreshCached庄蹋,這樣雖然會(huì)降低性能,但是下載圖片時(shí)會(huì)照顧到服務(wù)器返回的 caching control迷雪。
  • 問題 3:在加載圖片時(shí)限书,如何添加默認(rèn)的 progress indicator ?
    解決方案:在調(diào)用 -sd_setImageWithURL:方法之前章咧,先調(diào)用下面的方法:
    [imageView sd_setShowActivityIndicatorView:YES];
    [imageView sd_setIndicatorStyle:UIActivityIndicatorViewStyleGray];

五倦西、總結(jié)
SDWebImage作為一個(gè)優(yōu)秀的圖片加載框架,提供的使用方法和接口對(duì)開發(fā)者來說非常友好赁严。
其內(nèi)部實(shí)現(xiàn)多是采用Block的方式來實(shí)現(xiàn)回調(diào)扰柠,代碼閱讀起來可能沒有那么直觀。
內(nèi)部有用到了很多好的技術(shù)疼约,比如卤档,GCD,線程加鎖等程剥,可供我們學(xué)習(xí)劝枣。
SDWebImage中有兩個(gè)比較好用的宏定義定義之dispatch_main_sync_safe和dispatch_main_async_safe。

define dispatch_main_sync_safe(block)\

if ([NSThread isMainThread]) {\
    block();\
} else {\
    dispatch_sync(dispatch_get_main_queue(), block);\
}

define dispatch_main_async_safe(block)\

if ([NSThread isMainThread]) {\
    block();\
} else {\
    dispatch_async(dispatch_get_main_queue(), block);\
}

SDWebImage頻繁運(yùn)用了runtime中的關(guān)聯(lián)函數(shù)倡缠,用關(guān)聯(lián)函數(shù)關(guān)聯(lián)一個(gè)對(duì)象哨免,稱關(guān)聯(lián)對(duì)象,關(guān)聯(lián)對(duì)象相當(dāng)于實(shí)例變量昙沦,在類別里面,不能創(chuàng)建實(shí)例變量载荔,關(guān)聯(lián)對(duì)象就可以解決這種問題盾饮。
主要函數(shù)有:
objc_setAssociatedObject 相當(dāng)于 setValue:forKey 進(jìn)行關(guān)聯(lián)value對(duì)象
objc_getAssociatedObject 用來讀取對(duì)象
objc_AssociationPolicy 屬性 是設(shè)定該value在object內(nèi)的屬性,即 assgin, (retain,nonatomic)...等
objc_removeAssociatedObjects 函數(shù)來移除一個(gè)關(guān)聯(lián)對(duì)象懒熙,或者使用objc_setAssociatedObject函數(shù)將key指定的關(guān)聯(lián)對(duì)象設(shè)置為nil丘损。
相關(guān)參數(shù):
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
id object :表示關(guān)聯(lián)者,是一個(gè)對(duì)象工扎,變量名理所當(dāng)然也是object
const void *key :獲取被關(guān)聯(lián)者的索引key
id value :被關(guān)聯(lián)者徘钥,這里是一個(gè)block
objc_AssociationPolicy policy : 關(guān)聯(lián)時(shí)采用的協(xié)議,有assign肢娘,retain呈础,copy等協(xié)議舆驶,一般使 用OBJC_ASSOCIATION_RETAIN_NONATOMIC。
相關(guān)協(xié)議:
OBJC_ASSOCIATION_ASSIGN 等價(jià)于 @property(assign)而钞。
OBJC_ASSOCIATION_RETAIN_NONATOMIC等價(jià)于 @property(strong, nonatomic)沙廉。
OBJC_ASSOCIATION_COPY_NONATOMIC等價(jià)于@property(copy, nonatomic)。
OBJC_ASSOCIATION_RETAIN等價(jià)于@property(strong,atomic)臼节。
OBJC_ASSOCIATION_COPY等價(jià)于@property(copy, atomic)撬陵。
六、SDWebImage3.8.2與4.0的區(qū)別
SDWebImage4.0是一個(gè)大版本网缝,在結(jié)構(gòu)上和API方面都有所改動(dòng)巨税。
區(qū)別:
1、新增targetURL粉臊,存放原始圖像url垢夹;
2、新增一個(gè)FLAnimatedImageView+WebCache類维费,主要在動(dòng)圖支持上做了改進(jìn)果元,尤其是 GIF;
3犀盟、SDWebImage4.0新增一個(gè)UIView+WebCache類中而晒,將UIImageView+WebCache類中的方法移動(dòng)到UIView+WebCache類中,UIImageView對(duì)象依然響應(yīng)這些方法阅畴。

SDWebImage4.0新增了很多方法倡怎,詳細(xì)的在GitHub上看官方文檔。
https://github.com/rs/SDWebImage/blob/master/Docs/SDWebImage-4.0-Migration-guide.md

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贱枣,一起剝皮案震驚了整個(gè)濱河市监署,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纽哥,老刑警劉巖钠乏,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異春塌,居然都是意外死亡晓避,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門只壳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俏拱,“玉大人,你說我怎么就攤上這事吼句」兀” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵惕艳,是天一觀的道長(zhǎng)搞隐。 經(jīng)常有香客問我驹愚,道長(zhǎng),這世上最難降的妖魔是什么尔许? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任么鹤,我火速辦了婚禮,結(jié)果婚禮上味廊,老公的妹妹穿的比我還像新娘蒸甜。我一直安慰自己,他們只是感情好余佛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布柠新。 她就那樣靜靜地躺著,像睡著了一般辉巡。 火紅的嫁衣襯著肌膚如雪恨憎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天郊楣,我揣著相機(jī)與錄音憔恳,去河邊找鬼。 笑死净蚤,一個(gè)胖子當(dāng)著我的面吹牛钥组,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播今瀑,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼程梦,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了橘荠?” 一聲冷哼從身側(cè)響起屿附,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎哥童,沒想到半個(gè)月后挺份,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡如蚜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年压恒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片错邦。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖型宙,靈堂內(nèi)的尸體忽然破棺而出撬呢,到底是詐尸還是另有隱情,我是刑警寧澤妆兑,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布魂拦,位于F島的核電站毛仪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏芯勘。R本人自食惡果不足惜箱靴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望荷愕。 院中可真熱鬧衡怀,春花似錦、人聲如沸安疗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荐类。三九已至怖现,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間玉罐,已是汗流浹背屈嗤。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吊输,地道東北人饶号。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像璧亚,于是被迫代替她去往敵國和親讨韭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容