前言
從事iOS開發(fā)有一段時(shí)間了,為了成長鲁冯,決定開始著手寫博客猜极。這一階段中姜,博客主要內(nèi)容是解讀諸如:SDWebImage、AFNetWorking等優(yōu)秀的開源框架跟伏。
這段時(shí)間一直在拜讀博客園大神馬在路上的博客丢胚,他就有關(guān)于SDWebImage的解讀,很詳細(xì)酬姆,把很多值得學(xué)習(xí)的知識(shí)點(diǎn)凸顯了出來嗜桌,我受益匪淺。但是作為新手辞色,這些框架源碼中還是有很多我不太懂的細(xì)節(jié)知識(shí)點(diǎn)骨宠,所以浮定,我的目標(biāo)就是去解讀細(xì)碎的知識(shí)點(diǎn),讓自己能建立一個(gè)更加牢固的基礎(chǔ)知識(shí)體系层亿。歡迎批評指正桦卒!
解讀方法:先從頭文件開始,分析類功能匿又,每個(gè)方法功能方灾,然后解讀.m文件方法的具體實(shí)現(xiàn)。
正文
.h:
復(fù)制代碼
typedef NS_ENUM(NSInteger, SDImageFormat) {
SDImageFormatUndefined = -1,
SDImageFormatJPEG = 0,
SDImageFormatPNG,
SDImageFormatGIF,
SDImageFormatTIFF,
SDImageFormatWebP
};
- (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
復(fù)制代碼
這個(gè)類是NSData的分類碌更,分類作用是對類的功能擴(kuò)展裕偿。所以這個(gè)類是用來處理data的。
這個(gè)頭文件很簡單痛单,方法返回SDImageFormat是一個(gè)文件格式嘿棘。
文件頭:
定義:文件頭是位于文件開頭的一段承擔(dān)一定任務(wù)的數(shù)據(jù)。一般都在開頭的部分旭绒。
解釋:文件頭則是直接位于文件中的一段數(shù)據(jù),是文件的一部分鸟妙。計(jì)算機(jī)中的文件有很多類型,而相同類型的文件一般還會(huì)多多少少有一些不同的地方挥吵,文件的類型有EXE,COM,BMP,GIF,WMV,APE,RMVB,FLV,SWF,TXT,CPP,ASM等等重父。當(dāng)然有的文件沒有文件頭,比如TXT忽匈,系統(tǒng)根據(jù)擴(kuò)展名來識(shí)別文件房午,然后用不同的程序來打開這個(gè)文件。但是相同類型的文件也是有不同的地方的脉幢,比如相同一張圖片歪沃,但是文件大小不同嗦锐,而系統(tǒng)就可以根據(jù)文件頭來識(shí)別文件大小嫌松。簡單來說,文件頭是用來區(qū)分文件是什么類型的奕污。
文件頭的類型有很多萎羔,下面列舉一些文件頭:
1.JPG,文件頭:FFD8FFE1
2.PNG碳默,文件頭:89504E47
3.GIF贾陷,文件頭:47494638
4.TIFF,文件頭:49492A00
5.WebP嘱根,文件頭:524946462A73010057454250
.m文件
下面我們看.m文件
復(fù)制代碼
1 + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
2 if (!data) {
3 return SDImageFormatUndefined;
4 }
5
6 uint8_t c;
7 [data getBytes:&c length:1];
8 switch (c) {
9 case 0xFF:
10 return SDImageFormatJPEG;
11 case 0x89:
12 return SDImageFormatPNG;
13 case 0x47:
14 return SDImageFormatGIF;
15 case 0x49:
16 case 0x4D:
17 return SDImageFormatTIFF;
18 case 0x52:
19 // R as RIFF for WEBP
20 if (data.length < 12) {
21 return SDImageFormatUndefined;
22 }
23
24 NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
25 if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
26 return SDImageFormatWebP;
27 }
28 }
29 return SDImageFormatUndefined;
30 }
復(fù)制代碼
這里我們進(jìn)行逐行解讀:
unit8_t c髓废;點(diǎn)擊跳轉(zhuǎn)我們可以看到
typedef unsigned char uint8_t;
typedef的意思就是,用后者代替前者该抒。用unit8_t來表示無符號char慌洪。而char在C語言中表示字符型,長度為一個(gè)字節(jié)。
[data getBytes:&c length:1];點(diǎn)擊跳轉(zhuǎn)我們可以看到
1 - (void)getBytes:(void *)buffer length:(NSUInteger)length;
這個(gè)是NSData的方法冈爹,這個(gè)方法的作用是取出length個(gè)字節(jié)涌攻,存入buffer中。所以這行代碼的作用是频伤,取出文件data的第一個(gè)字節(jié)恳谎,然后存入c中。
接下來憋肖,我們可以看到是switch分支語句因痛,判斷取出的這個(gè)字節(jié)的內(nèi)容,返回對應(yīng)的文件格式岸更。
當(dāng)c==0x52時(shí)婚肆,判斷了data的長度,如果長度小于12坐慰,則此文件一定不是WebP较性。
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
如果大于12,則取出0-12個(gè)字節(jié)的數(shù)據(jù)结胀,然后轉(zhuǎn)為ASCII編碼赞咙,判斷字符串,若字符串是以RIFF開頭糟港,或者以WEBP結(jié)尾攀操,則文件為WebP格式。
總結(jié):
這個(gè)類功能比較簡單秸抚,就是根據(jù)文件二進(jìn)制數(shù)據(jù)速和,返回文件格式。是利用分類對NSData進(jìn)行功能擴(kuò)展剥汤。