版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.02.23 |
前言
我們做APP拜英,文字和圖片是絕對不可缺少的元素咧栗,特別是圖片一般存儲在圖床里面蒂誉,一般公司可以委托第三方保存怖侦,NB的公司也可以自己存儲圖片篡悟,ios有很多圖片加載的第三方框架,其中最優(yōu)秀的莫過于SDWebImage匾寝,它幾乎可以滿足你所有的需求搬葬,用了好幾年這個框架,今天想總結(jié)一下艳悔。感興趣的可以看其他幾篇急凰。
1. SDWebImage探究(一)
2. SDWebImage探究(二)
3. SDWebImage探究(三)
4. SDWebImage探究(四)
5. SDWebImage探究(五)
6. SDWebImage探究(六) —— 圖片類型判斷深入研究
7. SDWebImage探究(七) —— 深入研究圖片下載流程(一)之有關(guān)option的位移枚舉的說明
8. SDWebImage探究(八) —— 深入研究圖片下載流程(二)之開始下載并返回下載結(jié)果的總的方法
9. SDWebImage探究(九) —— 深入研究圖片下載流程(三)之下載之前的緩存查詢操作
10. SDWebImage探究(十) —— 深入研究圖片下載流程(四)之查詢緩存后的block回調(diào)處理
回顧
上一篇文章我們講述了查詢緩存后的block回調(diào)處理,其中就有SDWebImageDownloadToken
這個token的獲取猜年,這個token主要作用就是關(guān)聯(lián)每一個下載操作抡锈,可以用于取消一個下載疾忍,這一篇就詳細(xì)的說明一下這個token是如何生成和返回的。
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock;
這個方法就是返回token的方法床三,Creates a SDWebImageDownloader async downloader instance with a given URL
一罩,也可以這里理解,根據(jù)給定的url創(chuàng)建一個SDWebImageDownloader
異步的下載器撇簿。
SDWebImageDownloadToken的生成及返回
我們先看一下上面返回token方法的實現(xiàn)擒抛。
- (nullable SDWebImageDownloadToken *)downloadImageWithURL:(nullable NSURL *)url
options:(SDWebImageDownloaderOptions)options
progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
__weak SDWebImageDownloader *wself = self;
return [self addProgressCallback:progressBlock completedBlock:completedBlock forURL:url createCallback:^SDWebImageDownloaderOperation *{
__strong __typeof (wself) sself = wself;
NSTimeInterval timeoutInterval = sself.downloadTimeout;
if (timeoutInterval == 0.0) {
timeoutInterval = 15.0;
}
// In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
NSURLRequestCachePolicy cachePolicy = options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:cachePolicy
timeoutInterval:timeoutInterval];
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
request.HTTPShouldUsePipelining = YES;
if (sself.headersFilter) {
request.allHTTPHeaderFields = sself.headersFilter(url, [sself.HTTPHeaders copy]);
}
else {
request.allHTTPHeaderFields = sself.HTTPHeaders;
}
SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options];
operation.shouldDecompressImages = sself.shouldDecompressImages;
if (sself.urlCredential) {
operation.credential = sself.urlCredential;
} else if (sself.username && sself.password) {
operation.credential = [NSURLCredential credentialWithUser:sself.username password:sself.password persistence:NSURLCredentialPersistenceForSession];
}
if (options & SDWebImageDownloaderHighPriority) {
operation.queuePriority = NSOperationQueuePriorityHigh;
} else if (options & SDWebImageDownloaderLowPriority) {
operation.queuePriority = NSOperationQueuePriorityLow;
}
[sself.downloadQueue addOperation:operation];
if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[sself.lastAddedOperation addDependency:operation];
sself.lastAddedOperation = operation;
}
return operation;
}];
}
這里調(diào)用方法addProgressCallback
,返回這個SDWebImageDownloadToken
补疑。
1. SDWebImageDownloadToken的生成過程
- (nullable SDWebImageDownloadToken *)addProgressCallback:(SDWebImageDownloaderProgressBlock)progressBlock
completedBlock:(SDWebImageDownloaderCompletedBlock)completedBlock
forURL:(nullable NSURL *)url
createCallback:(SDWebImageDownloaderOperation *(^)(void))createCallback {
// The URL will be used as the key to the callbacks dictionary so it cannot be nil. If it is nil immediately call the completed block with no image or data.
if (url == nil) {
if (completedBlock != nil) {
completedBlock(nil, nil, nil, NO);
}
return nil;
}
__block SDWebImageDownloadToken *token = nil;
dispatch_barrier_sync(self.barrierQueue, ^{
SDWebImageDownloaderOperation *operation = self.URLOperations[url];
if (!operation) {
operation = createCallback();
self.URLOperations[url] = operation;
__weak SDWebImageDownloaderOperation *woperation = operation;
operation.completionBlock = ^{
dispatch_barrier_sync(self.barrierQueue, ^{
SDWebImageDownloaderOperation *soperation = woperation;
if (!soperation) return;
if (self.URLOperations[url] == soperation) {
[self.URLOperations removeObjectForKey:url];
};
});
};
}
id downloadOperationCancelToken = [operation addHandlersForProgress:progressBlock completed:completedBlock];
token = [SDWebImageDownloadToken new];
token.url = url;
token.downloadOperationCancelToken = downloadOperationCancelToken;
});
return token;
}
下面我們就一下來看一下這個方法的具體實現(xiàn)。
(a) 容錯處理
首先進(jìn)行的還是容錯處理歹撒,判斷url是否為空莲组,如果為空,就調(diào)用completedBlock(nil, nil, nil, NO);
暖夭,返回的圖像的數(shù)據(jù)都為空锹杈,并return nil
。
if (url == nil) {
if (completedBlock != nil) {
completedBlock(nil, nil, nil, NO);
}
return nil;
}
(b) 設(shè)置阻塞隊列并在其中生成token
這里使用的是dispatch_barrier_sync(dispatch_queue_t queue, DISPATCH_NOESCAPE dispatch_block_t block);
迈着,同步阻塞隊列竭望,與其類似的還有一個是異步阻塞隊列,他們的區(qū)別和使用裕菠,后面我會和大家分篇進(jìn)行說明咬清。
這里定義一個用于存放操作的字典,key就是url
@property (strong, nonatomic, nonnull) NSMutableDictionary<NSURL *, SDWebImageDownloaderOperation *> *URLOperations;
先查看該操作是否存在字典中
SDWebImageDownloaderOperation *operation = self.URLOperations[url];
然后調(diào)用NSOperation中的completionBlock
奴潘,@property (nullable, copy) void (^completionBlock)(void) API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
operation.completionBlock = ^{
dispatch_barrier_sync(self.barrierQueue, ^{
SDWebImageDownloaderOperation *soperation = woperation;
if (!soperation) return;
if (self.URLOperations[url] == soperation) {
[self.URLOperations removeObjectForKey:url];
};
});
};
在其中做的操作就是判斷該操作是不是在字典中旧烧,如果在,就從字典中移除画髓。這里仍然用的是阻塞dispatch_barrier_sync
的block掘剪。
然后調(diào)用方法,生成token中的一個屬性token.downloadOperationCancelToken
奈虾,并賦值夺谁。
- (nullable id)addHandlersForProgress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
completed:(nullable SDWebImageDownloaderCompletedBlock)completedBlock {
SDCallbacksDictionary *callbacks = [NSMutableDictionary new];
if (progressBlock) callbacks[kProgressCallbackKey] = [progressBlock copy];
if (completedBlock) callbacks[kCompletedCallbackKey] = [completedBlock copy];
dispatch_barrier_async(self.barrierQueue, ^{
[self.callbackBlocks addObject:callbacks];
});
return callbacks;
}
這里定義了一個字典,將相關(guān)的block copy后進(jìn)行存儲在字典中肉微,并且將該字典存在一個可變的數(shù)組callbackBlocks
中匾鸥。
typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
static NSString *const kProgressCallbackKey = @"progress";
static NSString *const kCompletedCallbackKey = @"completed";
@property (strong, nonatomic, nonnull) NSMutableArray<SDCallbacksDictionary *> *callbackBlocks;
SDWebImageDownloaderOperation的生成
生成token的那個方法中有一個block createCallback:(SDWebImageDownloaderOperation *(^)(void))createCallback
,它是一個具有返回值的block浪册,大家還記得這句代碼嗎扫腺?operation = createCallback();
,當(dāng)字典中查找的這個operation為nil的時候村象,就執(zhí)行這個block返回一個SDWebImageDownloaderOperation
對象笆环。
下面我們就一起看一下這個SDWebImageDownloaderOperation
的生成過程攒至。
(a)定義下載的超時
這里定義的是下載的超時,是15s躁劣,并且進(jìn)行了處理迫吐,如果時間間隔為0,那么就重新賦值為15s账忘。
NSTimeInterval timeoutInterval = sself.downloadTimeout;
if (timeoutInterval == 0.0) {
timeoutInterval = 15.0;
}
(b)緩存策略
為了防止?jié)撛诘闹貜?fù)緩存(NSURLCache + SDImageCache)
志膀,我們禁用圖像請求的緩存。
// In order to prevent from potential duplicate caching (NSURLCache + SDImageCache) we disable the cache for image requests if told otherwise
NSURLRequestCachePolicy cachePolicy = options & SDWebImageDownloaderUseNSURLCache ? NSURLRequestUseProtocolCachePolicy : NSURLRequestReloadIgnoringLocalCacheData;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:cachePolicy
timeoutInterval:timeoutInterval];
這里使用一個三目運算符鳖擒,當(dāng)傳入的options是SDWebImageDownloaderUseNSURLCache
時溉浙,那么NSURLRequestCachePolicy
的實例化對象cachePolicy
就是NSURLRequestUseProtocolCachePolicy
否則就是NSURLRequestReloadIgnoringLocalCacheData
。
下面我們看一下這個NSURLRequestCachePolicy
枚舉值
/*!
@enum NSURLRequestCachePolicy
@discussion The NSURLRequestCachePolicy enum defines constants that
can be used to specify the type of interactions that take place with
the caching system when the URL loading system processes a request.
Specifically, these constants cover interactions that have to do
with whether already-existing cache data is returned to satisfy a
URL load request.
NSURLRequestCachePolicy枚舉定義了常量可以用來當(dāng)指定URL加載系統(tǒng)處理請求時的
緩存系統(tǒng)發(fā)生時的交互類型 蒋荚。具體來說戳稽,這些常量涵蓋了必須做的交互,用來處理是否返回
已經(jīng)存在的緩存數(shù)據(jù)以滿足URL加載請求期升。
@constant NSURLRequestUseProtocolCachePolicy Specifies that the
caching logic defined in the protocol implementation, if any, is
used for a particular URL load request. This is the default policy
for URL load requests.
NSURLRequestUseProtocolCachePolicy指定協(xié)議實現(xiàn)中定義的緩存邏輯(如果有)
用于特定的URL加載請求惊奇。 這是URL加載請求的默認(rèn)策略。
@constant NSURLRequestReloadIgnoringLocalCacheData Specifies that the
data for the URL load should be loaded from the origin source. No
existing local cache data, regardless of its freshness or validity,
should be used to satisfy a URL load request.
NSURLRequestReloadIgnoringLocalCacheData指定應(yīng)該從原始源加載URL加載的數(shù)據(jù)播赁。
不使用現(xiàn)有的本地緩存數(shù)據(jù)(不管其新鮮度或有效性)滿足URL加載請求颂郎。
@constant NSURLRequestReloadIgnoringLocalAndRemoteCacheData Specifies that
not only should the local cache data be ignored, but that proxies and
other intermediates should be instructed to disregard their caches
so far as the protocol allows. Unimplemented.
NSURLRequestReloadIgnoringLocalAndRemoteCacheData指定不僅忽略本地緩存數(shù)據(jù),而且
應(yīng)該指示代理和其他中轉(zhuǎn)忽略它們的緩存容为,只要協(xié)議允許乓序。未實現(xiàn)。
@constant NSURLRequestReloadIgnoringCacheData Older name for
NSURLRequestReloadIgnoringLocalCacheData.
NSURLRequestReloadIgnoringLocalCacheData的較早名稱舟奠。
@constant NSURLRequestReturnCacheDataElseLoad Specifies that the
existing cache data should be used to satisfy a URL load request,
regardless of its age or expiration date. However, if there is no
existing data in the cache corresponding to a URL load request,
the URL is loaded from the origin source.
NSURLRequestReturnCacheDataElseLoad指定應(yīng)使用現(xiàn)有緩存數(shù)據(jù)來滿足URL加載請求竭缝,
而不管其緩存時間或過期日期。 但是沼瘫,如果沒有與URL加載請求相對應(yīng)的現(xiàn)有的緩存數(shù)據(jù)抬纸,
則URL將從源數(shù)據(jù)源加載膜蛔。
@constant NSURLRequestReturnCacheDataDontLoad Specifies that the
existing cache data should be used to satisfy a URL load request,
regardless of its age or expiration date. However, if there is no
existing data in the cache corresponding to a URL load request, no
attempt is made to load the URL from the origin source, and the
load is considered to have failed. This constant specifies a
behavior that is similar to an "offline" mode.
NSURLRequestReturnCacheDataDontLoad指定應(yīng)使用現(xiàn)有緩存數(shù)據(jù)來滿足URL加載請求,
而不管其緩存時間或到期日期。 但是悍募,如果緩存中沒有與URL加載請求相對應(yīng)的現(xiàn)有數(shù)據(jù)喜鼓,
則不會嘗試從源數(shù)據(jù)源加載URL顿锰,并且認(rèn)為加載失敗胳赌。 此常數(shù)指定與“離線”模式類似的行為捍掺。
@constant NSURLRequestReloadRevalidatingCacheData Specifies that
the existing cache data may be used provided the origin source
confirms its validity, otherwise the URL is loaded from the
origin source. Unimplemented.
NSURLRequestReloadRevalidatingCacheData指定可以使用現(xiàn)有的緩存數(shù)據(jù)不瓶,只要原始源
確認(rèn)其有效性麦备,否則URL將從原始源加載。未實現(xiàn)削彬。
*/
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
NSURLRequestUseProtocolCachePolicy = 0,
NSURLRequestReloadIgnoringLocalCacheData = 1,
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
NSURLRequestReturnCacheDataElseLoad = 2,
NSURLRequestReturnCacheDataDontLoad = 3,
NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
};
這里給大家翻譯了一下覆劈,看了應(yīng)該好理解了不少吧坤候。
(c)cookies處理
request.HTTPShouldHandleCookies = (options & SDWebImageDownloaderHandleCookies);
只要options是SDWebImageDownloaderHandleCookies,那么就是YES闽寡,否則就是NO。
這個HTTPShouldHandleCookies
是NSURLRequest的屬性下隧。
/*!
@abstract Decide whether default cookie handling will happen for
this request (YES if cookies should be sent with and set for this request;
otherwise NO).
@discussion The default is YES - in other words, cookies are sent from and
stored to the cookie manager by default.
NOTE: In releases prior to 10.3, this value is ignored
*/
@property BOOL HTTPShouldHandleCookies;
這個屬性奢人,決定是否對此請求執(zhí)行默認(rèn)的cookie處理(如果cookie應(yīng)與此請求一起發(fā)送并設(shè)置何乎,則為YES指孤;否則為NO)蒸殿。默認(rèn)為YES,換句話說宏所,Cookie默認(rèn)情況下是從cookie管理器發(fā)送并存儲到cookie管理器的玖雁。 注:在10.3之前的版本中,該值被忽略盖腕。
(d)是否使用pipelining
/*!
@abstract Sets whether the request should not wait for the previous response
before transmitting (YES if the receiver should transmit before the previous response is
received. NO to wait for the previous response before transmitting)
@discussion Calling this method with a YES value does not guarantee HTTP
pipelining behavior. This method may have no effect if an HTTP proxy is
configured, or if the HTTP request uses an unsafe request method (e.g., POST
requests will not pipeline). Pipelining behavior also may not begin until
the second request on a given TCP connection. There may be other situations
where pipelining does not occur even though YES was set.
HTTP 1.1 allows the client to send multiple requests to the server without
waiting for a response. Though HTTP 1.1 requires support for pipelining,
some servers report themselves as being HTTP 1.1 but do not support
pipelining (disconnecting, sending resources misordered, omitting part of
a resource, etc.).
*/
設(shè)置請求是否在發(fā)送之前不等待先前的響應(yīng)(如果接收器應(yīng)在接收到前一個響應(yīng)之前發(fā)送,則為YES浓镜;
在發(fā)送之前等待先前的響應(yīng)就設(shè)置為NO)溃列。以YES值調(diào)用此方法并不保證HTTP流水線行為。 如果配置
了HTTP代理膛薛,或者HTTP請求使用不安全的請求方法(例如听隐,POST請求不會流水線),則此方法可能不起
作用哄啄。 在給定的TCP連接上的第二個請求之前雅任,流水線行為也可能不會開始。 即使設(shè)置了YES咨跌,也可能會
出現(xiàn)流水線不會發(fā)生的其他情況沪么。 HTTP 1.1允許客戶端向服務(wù)器發(fā)送多個請求,而無需等待響應(yīng)锌半。 盡管HTTP 1.1
需要流水線支持禽车,但有些服務(wù)器會將自己報告為HTTP 1.1,但不支持流水線操作(斷開連接,發(fā)送資源亂序殉摔,忽略部分資源等)州胳。
@property BOOL HTTPShouldUsePipelining API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));
上面給大家翻譯的應(yīng)該很好理解,其實還可以這么理解逸月,通常默認(rèn)情況下請求和響應(yīng)是順序的, 也就是說請求–>得到響應(yīng)后栓撞,再請求。如果將HTTPShouldUsePipelining
設(shè)置為YES, 則允許不必等到response
, 就可以再次請求碗硬。這個會很大的提高網(wǎng)絡(luò)請求的效率瓤湘,但是也可能會出問題。
因為客戶端無法正確的匹配請求與響應(yīng), 所以這依賴于服務(wù)器必須保證肛响,響應(yīng)的順序與客戶端請求的順序一致岭粤,如果服務(wù)器不能保證這一點,那可能導(dǎo)致響應(yīng)和請求混亂特笋,具體原理圖如下所示剃浇。
(e)HTTP頭區(qū)域的設(shè)置
/*!
@abstract Sets the HTTP header fields of the receiver to the given
dictionary.
@discussion This method replaces all header fields that may have
existed before this method call.
<p>Since HTTP header fields must be string values, each object and
key in the dictionary passed to this method must answer YES when
sent an <tt>-isKindOfClass:[NSString class]</tt> message. If either
the key or value for a key-value pair answers NO when sent this
message, the key-value pair is skipped.
*/
將接收器的HTTP頭字段設(shè)置為給定的字典。此方法替換此方法調(diào)用之前可能存在的所有頭字段猎物。
由于HTTP頭字段必須是字符串值虎囚,因此傳遞給此方法的字典中的每個對象和鍵必須在發(fā)送<tt> -isKindOfClass:[NSString類] </ tt>
消息時回答YES。 如果鍵值對的鍵或值在發(fā)送此消息時回答NO蔫磨,則會跳過鍵值對淘讥。
@property (nullable, copy) NSDictionary<NSString *, NSString *> *allHTTPHeaderFields;
這個屬性返回一個包含所有接受者HTTP頭區(qū)域的字典。
這里進(jìn)行了判斷
if (sself.headersFilter) {
request.allHTTPHeaderFields = sself.headersFilter(url, [sself.HTTPHeaders copy]);
}
else {
request.allHTTPHeaderFields = sself.HTTPHeaders;
}
如果SDWebImageDownloaderHeadersFilterBlock這個block不為空堤如,那么就返回一個SDHTTPHeadersDictionary
不可變字典蒲列,如果為空就返回一個可變字典@property (strong, nonatomic, nullable) SDHTTPHeadersMutableDictionary *HTTPHeaders
。
typedef NSDictionary<NSString *, NSString *> SDHTTPHeadersDictionary;
typedef NSMutableDictionary<NSString *, NSString *> SDHTTPHeadersMutableDictionary;
typedef SDHTTPHeadersDictionary * _Nullable (^SDWebImageDownloaderHeadersFilterBlock)(NSURL * _Nullable url, SDHTTPHeadersDictionary * _Nullable headers);
/**
* Set filter to pick headers for downloading image HTTP request.
*
* This block will be invoked for each downloading image request, returned
* NSDictionary will be used as headers in corresponding HTTP request.
*/
@property (nonatomic, copy, nullable) SDWebImageDownloaderHeadersFilterBlock headersFilter;
(f)實例化SDWebImageDownloaderOperation并設(shè)置是否解壓縮圖片
SDWebImageDownloaderOperation *operation = [[sself.operationClass alloc] initWithRequest:request inSession:sself.session options:options];
operation.shouldDecompressImages = sself.shouldDecompressImages;
這里實例化SDWebImageDownloaderOperation
的時候需要傳入上下文session搀罢,如下所示蝗岖。
// The session in which data tasks will run
@property (strong, nonatomic) NSURLSession *session;
并設(shè)置是否解壓縮圖片
/**
* Decompressing images that are downloaded and cached can improve performance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
*/
@property (assign, nonatomic) BOOL shouldDecompressImages;
解壓下載和緩存的圖像可以提高性能,但會占用大量內(nèi)存榔至。默認(rèn)設(shè)置為YES抵赢。 如果由于內(nèi)存消耗過多而導(dǎo)致崩潰,請將其設(shè)置為NO唧取。
(g)NSURLCredential 身份認(rèn)證
web 服務(wù)可以在返回 http 響應(yīng)時附帶認(rèn)證要求 challenge铅鲤,作用是詢問 http 請求的發(fā)起方是誰,這時發(fā)起方應(yīng)提供正確的用戶名和密碼(即認(rèn)證信息)枫弟,然后 web 服務(wù)才會返回真正的 http 響應(yīng)邢享。
下面看一下身份驗證
if (sself.urlCredential) {
operation.credential = sself.urlCredential;
}
else if (sself.username && sself.password) {
operation.credential = [NSURLCredential credentialWithUser:sself.username password:sself.password persistence:NSURLCredentialPersistenceForSession];
}
這里,urlCredential
屬性定義如下:
/**
* Set the default URL credential to be set for request operations.
*/
@property (strong, nonatomic, nullable) NSURLCredential *urlCredential;
操作SDWebImageDownloaderOperation
的credential
定義如下:
/**
* The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`.
*
* This will be overridden by any shared credentials that exist for the username or password of the request URL, if present.
*/
@property (nonatomic, strong, nullable) NSURLCredential *credential;
這里的邏輯就是這個驗證如果存在就直接通過屬性賦值過去淡诗,如果不存在那么就直接利用蘋果的API直接創(chuàng)建驼仪。這里創(chuàng)建需要傳入一個用戶名掸犬、密碼還有一個枚舉值,下面看一下這個枚舉值绪爸。
/*!
@enum NSURLCredentialPersistence
@abstract Constants defining how long a credential will be kept around
@constant NSURLCredentialPersistenceNone This credential won't be saved.
@constant NSURLCredentialPersistenceForSession This credential will only be stored for this session.
@constant NSURLCredentialPersistencePermanent This credential will be stored permanently. Note: Whereas in Mac OS X any application can access any credential provided the user gives permission, in iPhone OS an application can access only its own credentials.
@constant NSURLCredentialPersistenceSynchronizable This credential will be stored permanently. Additionally, this credential will be distributed to other devices based on the owning AppleID.
Note: Whereas in Mac OS X any application can access any credential provided the user gives permission, on iOS an application can
access only its own credentials.
*/
@abstract常量定義證書將保留多久
@constant NSURLCredentialPersistenceNone這個證書不會被保存湾碎。
@constant NSURLCredentialPersistenceForSession此憑證將僅存儲于此會話中。
@constant NSURLCredentialPersistencePermanent這個憑證將永久存儲奠货。 注意:在Mac OS X中介褥,任何應(yīng)用程序都可以訪問任何憑據(jù),只要用戶授予權(quán)限递惋,在iPhone OS中柔滔,應(yīng)用程序只能訪問自己的憑據(jù)。
@constant NSURLCredentialPersistenceSynchronizable此憑證將永久存儲萍虽。 此外睛廊,此憑證將根據(jù)擁有的AppleID分配給其他設(shè)備。 注意:在Mac OS X中杉编,任何應(yīng)用程序都可以訪問任何憑據(jù)超全,只要用戶授予權(quán)限即可,一個iOS程序只能訪問自己的憑據(jù)邓馒。
typedef NS_ENUM(NSUInteger, NSURLCredentialPersistence) {
NSURLCredentialPersistenceNone,
NSURLCredentialPersistenceForSession,
NSURLCredentialPersistencePermanent,
NSURLCredentialPersistenceSynchronizable API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0))
};
(h)隊列的優(yōu)先級
這里也設(shè)置了隊列的優(yōu)先級嘶朱,如下所示:
if (options & SDWebImageDownloaderHighPriority) {
operation.queuePriority = NSOperationQueuePriorityHigh;
} else if (options & SDWebImageDownloaderLowPriority) {
operation.queuePriority = NSOperationQueuePriorityLow;
}
這里,如果options是SDWebImageDownloaderHighPriority光酣,也就是高優(yōu)先級疏遏,那么就設(shè)置NSOperation這個屬性@property NSOperationQueuePriority queuePriority;
的優(yōu)先級為NSOperationQueuePriorityHigh
,否則為NSOperationQueuePriorityLow
救军,這里看一下這個枚舉值财异。
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
這個很好理解就不多說了。
(i)設(shè)置隊列的執(zhí)行順序
下面就是將操作加入到隊列并設(shè)置隊列的執(zhí)行順序唱遭,同時為LIFO類型的隊列添加依賴戳寸,防止出現(xiàn)錯亂。
/**
* Changes download operations execution order. Default value is `SDWebImageDownloaderFIFOExecutionOrder`.
*/
@property (assign, nonatomic) SDWebImageDownloaderExecutionOrder executionOrder;
@property (strong, nonatomic, nonnull) NSOperationQueue *downloadQueue;
@property (weak, nonatomic, nullable) NSOperation *lastAddedOperation;
[sself.downloadQueue addOperation:operation];
if (sself.executionOrder == SDWebImageDownloaderLIFOExecutionOrder) {
// Emulate LIFO execution order by systematically adding new operations as last operation's dependency
[sself.lastAddedOperation addDependency:operation];
sself.lastAddedOperation = operation;
}
這里隊列執(zhí)行順序是一個枚舉胆萧,其實就是隊列和堆棧兩種隊列執(zhí)行順序,如下所示:
typedef NS_ENUM(NSInteger, SDWebImageDownloaderExecutionOrder) {
/**
* Default value. All download operations will execute in queue style (first-in-first-out).
默認(rèn)值俐东,所有下載操作都以隊列的形式執(zhí)行跌穗。
*/
SDWebImageDownloaderFIFOExecutionOrder,
/**
* All download operations will execute in stack style (last-in-first-out).
所有下載操作都以堆棧的形式執(zhí)行。
*/
SDWebImageDownloaderLIFOExecutionOrder
};
這些都設(shè)置好了虏辫,就可以返回對應(yīng)的操作對象SDWebImageDownloaderOperation *operation
了蚌吸。
后記
本篇已結(jié)束,后面更精彩~~~