1. 網(wǎng)絡(luò)請(qǐng)求下載圖片
YY用的是NSURLConnection,這個(gè)其實(shí)可以用NSURLSession替換
2. 圖片解碼
2.1 判斷圖片格式
2.2 不同圖片格式對(duì)應(yīng)不同的顯示方式
-
JPEG, PNG, GIF都支持逐行顯示(baseline)
image_baseline.gif -
PNG,GIF支持隔行顯示(interlaced)
image_interlaced.gif -
只有JPEG支持漸進(jìn)式加載
image_progressive.gif
2.3 如何判斷圖片格式
取圖片數(shù)據(jù)的第一個(gè)字節(jié)
//通過圖片Data數(shù)據(jù)第一個(gè)字節(jié) 來獲取圖片擴(kuò)展名
- (NSString *)contentTypeForImageData:(NSData *)data{
uint8_t c;
[data getBytes:&c length:1];
switch (c) {
case 0xFF:
return @"jpeg";
case 0x89:
return @"png";
case 0x47:
return @"gif";
case 0x49:
case 0x4D:
return @"tiff";
case 0x52:
if ([data length] < 12) {
return nil;
}
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return @"webp";
}
return nil;
}
return nil;
}
2.4 圖片緩存設(shè)置
NSURLRequest 有個(gè) cachePolicy 屬性,它根據(jù)以下常量指定了請(qǐng)求的緩存行為:
- NSURLRequestUseProtocolCachePolicy: 對(duì)特定的 URL 請(qǐng)求使用網(wǎng)絡(luò)協(xié)議中實(shí)現(xiàn)的緩存邏輯。這是默認(rèn)的策略。
- NSURLRequestReloadIgnoringLocalCacheData:數(shù)據(jù)需要從原始地址加載。不使用現(xiàn)有緩存。
- NSURLRequestReloadIgnoringLocalAndRemoteCacheData:不僅忽略本地緩存,同時(shí)也忽略代理服務(wù)器或其他中間介質(zhì)目前已有的、協(xié)議允許的緩存。
- NSURLRequestReturnCacheDataElseLoad:無(wú)論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請(qǐng)求所對(duì)應(yīng)的數(shù)據(jù),那么從原始地址加載數(shù)據(jù)。
- NSURLRequestReturnCacheDataDontLoad:無(wú)論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請(qǐng)求所對(duì)應(yīng)的數(shù)據(jù),那么放棄從原始地址加載數(shù)據(jù),請(qǐng)求視為失?。矗骸半x線”模式)。
- NSURLRequestReloadRevalidatingCacheData:從原始地址確認(rèn)緩存數(shù)據(jù)的合法性后,緩存數(shù)據(jù)就可以使用,否則從原始地址加載。
如果你需要更精確的緩存策略,NSURLSessionDataDelegate代理里的
URLSession:dataTask:willCacheResponse:completionHandler:方法或者NSURLConnection的connection:willCacheResponse:可以實(shí)現(xiàn)
2.5 為什么用pthread_mutex_lock對(duì)圖片原始處理時(shí)加鎖,怎么使用?
之所以用pthread_mutex_lock是因?yàn)閐ispacth_semaphore無(wú)法解決遞歸調(diào)用問題,同時(shí)性能上NSRecursiveLock也沒有它好,而處理圖片二進(jìn)制數(shù)據(jù)對(duì)性能有一定要求,所以用pthread_mutex_lock
YYWebImage的源碼如下
- (instancetype)initWithScale:(CGFloat)scale {
self = [super init];
if (scale <= 0) scale = 1;
_scale = scale;
_framesLock = dispatch_semaphore_create(1);
pthread_mutexattr_t attr;
pthread_mutexattr_init (&attr);
pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);//設(shè)置鎖為遞歸鎖
pthread_mutex_init (&_lock, &attr);
pthread_mutexattr_destroy (&attr);
return self;
}
- (BOOL)updateData:(NSData *)data final:(BOOL)final {
BOOL result = NO;
pthread_mutex_lock(&_lock);
result = [self _updateData:data final:final];
pthread_mutex_unlock(&_lock);
return result;
}
關(guān)于pthread_mutex_lock 的使用詳見這里
2.6 PNG圖片的解碼
對(duì)于png,作者是拿到全部數(shù)據(jù)后再渲染,我之前做過一個(gè)邊拿數(shù)據(jù)邊渲染的測(cè)試,結(jié)果很耗資源;而jpeg圖片,則是邊拿到數(shù)據(jù)邊渲染


