前言
从事iOS开发有一段时间了,为了成长,决定开始着手写博客。这一阶段,博客主要内容是解读诸如:SDWebImage、AFNetWorking等优秀的开源框架。
这段时间一直在拜读博客园大神马在路上的博客,他就有关于SDWebImage的解读,很详细,把很多值得学习的知识点凸显了出来,我受益匪浅。但是作为新手,这些框架源码中还是有很多我不太懂的细节知识点,所以,我的目标就是去解读细碎的知识点,让自己能建立一个更加牢固的基础知识体系。欢迎批评指正!
解读方法:先从头文件开始,分析类功能,每个方法功能,然后解读.m文件方法的具体实现。
正文
.h:
typedef NS_ENUM(NSInteger, SDImageFormat) { SDImageFormatUndefined = -1, SDImageFormatJPEG = 0, SDImageFormatPNG, SDImageFormatGIF, SDImageFormatTIFF, SDImageFormatWebP }; + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
这个类是NSData的分类,分类作用是对类的功能扩展。所以这个类是用来处理data的。
这个头文件很简单,方法返回SDImageFormat是一个文件格式。
文件头:
定义:文件头是位于文件开头的一段承担一定任务的数据。一般都在开头的部分。
解释:文件头则是直接位于文件中的一段数据,是文件的一部分。计算机中的文件有很多类型,而相同类型的文件一般还会多多少少有一些不同的地方,文件的类型有EXE,COM,BMP,GIF,WMV,APE,RMVB,FLV,SWF,TXT,CPP,ASM等等。当然有的文件没有文件头,比如TXT,系统根据扩展名来识别文件,然后用不同的程序来打开这个文件。但是相同类型的文件也是有不同的地方的,比如相同一张图片,但是文件大小不同,而系统就可以根据文件头来识别文件大小。简单来说,文件头是用来区分文件是什么类型的。
文件头的类型有很多,下面列举一些文件头:
1.JPG,文件头:FFD8FFE1
2.PNG,文件头:89504E47
3.GIF,文件头:47494638
4.TIFF,文件头:49492A00
5.WebP,文件头:524946462A73010057454250
.m文件
下面我们看.m文件
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 }
这里我们进行逐行解读:
unit8_t c;点击跳转我们可以看到
typedef unsigned char uint8_t;
typedef的意思就是,用后者代替前者。用unit8_t来表示无符号char。而char在C语言中表示字符型,长度为一个字节。
[data getBytes:&c length:1];点击跳转我们可以看到
1 - (void)getBytes:(void *)buffer length:(NSUInteger)length;
这个是NSData的方法,这个方法的作用是取出length个字节,存入buffer中。所以这行代码的作用是,取出文件data的第一个字节,然后存入c中。
接下来,我们可以看到是switch分支语句,判断取出的这个字节的内容,返回对应的文件格式。
当c==0x52时,判断了data的长度,如果长度小于12,则此文件一定不是WebP。
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
如果大于12,则取出0-12个字节的数据,然后转为ASCII编码,判断字符串,若字符串是以RIFF开头,或者以WEBP结尾,则文件为WebP格式。
总结:
这个类功能比较简单,就是根据文件二进制数据,返回文件格式。是利用分类对NSData进行功能扩展。
欢迎批评指正!