前言
YYKit是iOS组件的集合,这个框架的代码量很大,这里就分出几个独立的部分。
- YYModel - iOS高性能模型框架
- YYCache - iOS高性能缓存框架
- YYImage - iOS的图像框架用于显示/编码/解码动画Webp,APNG,GIF
- YYWebImage - 异步图像加载框架
- YYText - iOS强大的文本组件
- YYKeyBoardManager - 访问键盘视图并跟踪键盘动画
- YYDispatchQueuePool - iOS使用程序类来管理全局调度队列
- YYCategories - Foundation和UIKit的一组有用分类
安装
CocoaPods
- Podfile 中添加 pod 'YYKit'
- 运行pod install 或者 pod update
- 引入 <YYKit/YYkit.h>
基本框架
下面我们就看一下YYKit的基本框架。
NSString+YYAdd 框架
基本结构
下面我们来看下NSString分类 NSString+YYAdd 的架构,如下图所示
其实这里面包含了六个部分:
- Hash
- Encode and decode
- Drawing
- Regular Express
- NSNumber Compatible
- Utilities
接下来,我们就将一部分一部分的进行分析其接口API
一、Hash
下面我们来看看Hash这部分的接口
#pragma mark - Hash
///=============================================================================
/// @name Hash
///=============================================================================
/**
Returns a lowercase NSString for md2 hash.
*/
- (nullable NSString *)md2String;
/**
Returns a lowercase NSString for md4 hash.
*/
- (nullable NSString *)md4String;
/**
Returns a lowercase NSString for md5 hash.
*/
- (nullable NSString *)md5String;
/**
Returns a lowercase NSString for sha1 hash.
*/
- (nullable NSString *)sha1String;
/**
Returns a lowercase NSString for sha224 hash.
*/
- (nullable NSString *)sha224String;
/**
Returns a lowercase NSString for sha256 hash.
*/
- (nullable NSString *)sha256String;
/**
Returns a lowercase NSString for sha384 hash.
*/
- (nullable NSString *)sha384String;
/**
Returns a lowercase NSString for sha512 hash.
*/
- (nullable NSString *)sha512String;
/**
Returns a lowercase NSString for hmac using algorithm md5 with key.
@param key The hmac key.
*/
- (nullable NSString *)hmacMD5StringWithKey:(NSString *)key;
/**
Returns a lowercase NSString for hmac using algorithm sha1 with key.
@param key The hmac key.
*/
- (nullable NSString *)hmacSHA1StringWithKey:(NSString *)key;
/**
Returns a lowercase NSString for hmac using algorithm sha224 with key.
@param key The hmac key.
*/
- (nullable NSString *)hmacSHA224StringWithKey:(NSString *)key;
/**
Returns a lowercase NSString for hmac using algorithm sha256 with key.
@param key The hmac key.
*/
- (nullable NSString *)hmacSHA256StringWithKey:(NSString *)key;
/**
Returns a lowercase NSString for hmac using algorithm sha384 with key.
@param key The hmac key.
*/
- (nullable NSString *)hmacSHA384StringWithKey:(NSString *)key;
/**
Returns a lowercase NSString for hmac using algorithm sha512 with key.
@param key The hmac key.
*/
- (nullable NSString *)hmacSHA512StringWithKey:(NSString *)key;
/**
Returns a lowercase NSString for crc32 hash.
*/
- (nullable NSString *)crc32String;
其实这部分接口做的是两部分的功能:
- 对字符串进行 md2、md4、md5、sha1、sha224、sha256、sha384、sha512进行加密。
- 对字符串进行 md4、md5、sha1、sha224、sha256、sha384、sha512与指定的key进行加密。
- 进行crc32加密。
下面我们就对指定的两个具有代表性的方法实现进行说明和解析。
sha512
首先我们看一下这个方法的接口调用示例和实现。
1. 接口调用示例
/**
Returns a lowercase NSString for sha512 hash.
*/
- (nullable NSString *)sha512String;
下面我们就调用一下
NSString *str = @"abcdefgh";
NSString *sha512Str = [str sha512String];
NSLog(@"sha512Str = %@",sha512Str);
NSLog(@"sha512Str length = %ld",sha512Str.length);
接着我们看一下输出结果:
2023-04-03 14:02:42.331463+0800 YYKitDemo[866:3899739] sha512Str = a3a8c81bc97c2560010d7389bc88aac974a104e0e2381220c6e084c4dccd1d2d17d4f86db31c2a851dc80e6681d74733c55dcd03dd96f6062cdda12a291ae6ce
2023-04-03 14:02:42.331545+0800 YYKitDemo[866:3899739] sha512Str length = 128
可以看见,加密后数据为128位十六进制数,换算成二进制数就是512位
2.接口实现
下面我们就看一下接口的实现
- (NSString *)sha512String {
return [[self dataUsingEncoding:NSUTF8StringEncoding] sha512String];
}
这里首先调用的就是系统的 NSString 接口 dataUseingEncoding: 方法,将NSString转换为NSData对象,- (nullable NSData *)dataUsingEncoding:(NSStringEncoding)encoding 。
下面这里就是调用 NSData+YYAdd分类里面的方法sha512String,将NSData对象进行加密后转化为NSString对象
- (NSString *)sha512String {
unsigned char result[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(self.bytes, (CC_LONG)self.length, result);
NSMutableString *hash = [NSMutableString
stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++) {
[hash appendFormat:@"%02x", result[i]];
}
return hash;
}
上面就是简单的实现,其他sha224等的实现都是类似的。
带key的sha512
首先我们看一下这个方法的接口调用示例和实现
1.示例
NSString *str = @"abcdefgh";
NSString *sha512Str = [str hmacSHA512StringWithKey:@"zzz"];
NSLog(@"sha512Str = %@",sha512Str);
NSLog(@"sha512Str length = %ld",sha512Str.length);
2023-04-03 14:10:49.802227+0800 YYKitDemo[1155:3910766] sha512Str = e64db1c1b01c362931b283d28cfbf6baafd807c10cf07328cda9b37fb73b4571a76beb15d7dc6d16888d593a233974679af8a49e0543edbfeab8790eb86bb5c9
2023-04-03 14:10:49.802351+0800 YYKitDemo[1155:3910766] sha512Str length = 128
接口实现
- (NSString *)hmacSHA512StringWithKey:(NSString *)key {
return [[self dataUsingEncoding:NSUTF8StringEncoding]
hmacSHA512StringWithKey:key];
}
下面就是NSData的分类里面了
- (NSString *)hmacSHA512StringWithKey:(NSString *)key {
return [self hmacStringUsingAlg:kCCHmacAlgSHA512 withKey:key];
}
- (NSString *)hmacStringUsingAlg:(CCHmacAlgorithm)alg withKey:(NSString *)key {
size_t size;
switch (alg) {
case kCCHmacAlgMD5: size = CC_MD5_DIGEST_LENGTH; break;
case kCCHmacAlgSHA1: size = CC_SHA1_DIGEST_LENGTH; break;
case kCCHmacAlgSHA224: size = CC_SHA224_DIGEST_LENGTH; break;
case kCCHmacAlgSHA256: size = CC_SHA256_DIGEST_LENGTH; break;
case kCCHmacAlgSHA384: size = CC_SHA384_DIGEST_LENGTH; break;
case kCCHmacAlgSHA512: size = CC_SHA512_DIGEST_LENGTH; break;
default: return nil;
}
unsigned char result[size];
const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
CCHmac(alg, cKey, strlen(cKey), self.bytes, self.length, result);
NSMutableString *hash = [NSMutableString stringWithCapacity:size * 2];
for (int i = 0; i < size; i++) {
[hash appendFormat:@"%02x", result[i]];
}
return hash;
}
这个也很好理解,和上面不带key的方法实现相比,不同的是这里用的是系统方法 CCHmac。
二、Encode and decode
主要是包括:base64编码和解码、URL的UTF-8编码以及常见的HTML转义实体。原理同上
HTML转义实体: 例如 a > b 转义后 a<b
三、Drawing
- (CGSize)sizeForFont:(UIFont *)font size:(CGSize)size mode:(NSLineBreakMode)lineBreakMode
这个方法的作用就是返回给定的字符串边界的宽度和高度。这里size参数的意思是字符串的最大可接受大小。此值用于计算行会发生断裂和换行的位置
示例
NSString *str1 = @"说法发链接嘎嘎我给我阿萨法久啊射流风机萨芬较大生发剂噶防静电撒发发设计费萨法大丰收地方大";
CGSize stringSize = [str1 sizeForFont:[UIFont systemFontOfSize:16.0] size:CGSizeMake(200, 500) mode:NSLineBreakByCharWrapping];
NSLog(@"字符串的大小为 = %@",NSStringFromCGSize(stringSize));
输出结果
2023-04-03 14:28:20.489941+0800 YYKitDemo[1548:3929096] 字符串的大小为 = {195.84, 76.375}
方法的实现
这里其实还是利用NSString的原生方法
boundingRectWithSize: options: attributes: context:
其他方法同理
例如:
- (CGFloat)widthForFont:(UIFont *)font;
此处传入的size为最大值
传入的换行模式为:NSLineBreakByWordWrapping
四、Regular Expression
我们来详细的看一下这个接口 API
- (BOOL)matchesRegex:(NSString *)regex options:(NSRegularExpressionOptions)options;
该方法的作用是根据固定的匹配的表达式,判断给定的字符串和调用者是否匹配
示例
NSString *str2 = @"A";
BOOL isMatch = [str2 matchesRegex:@"B" options:NSRegularExpressionCaseInsensitive];
NSLog(@"是否匹配 = %d",isMatch);
打印结果:
2023-04-03 14:38:28.890424+0800 YYKitDemo[1794:3941628] 是否匹配 = 0
示例二:
NSString *str3 = @"A";
BOOL isMatch1 = [str3 matchesRegex:@"a" options:NSRegularExpressionCaseInsensitive];
NSLog(@"是否匹配 = %d",isMatch1);
打印结果:
2023-04-03 14:39:28.956567+0800 YYKitDemo[1829:3943455] 是否匹配 = 1
上面这个例子 NSRegularExpressionCaseInsensitive 也就是不区分大小写的比较。
方法的实现
- (BOOL)matchesRegex:(NSString *)regex options:(NSRegularExpressionOptions)options {
NSRegularExpression *pattern = [NSRegularExpression regularExpressionWithPattern:regex options:options error:NULL];
if (!pattern) return NO;
return ([pattern numberOfMatchesInString:self options:0 range:NSMakeRange(0, self.length)] > 0);
}
方法中有一个枚举值,就是 NSRegularExpressionOptions 下面我们就看一下这个枚举值。
typedef NS_OPTIONS(NSUInteger, NSRegularExpressionOptions) {
NSRegularExpressionCaseInsensitive = 1 << 0, /* Match letters in the pattern independent of case. */
NSRegularExpressionAllowCommentsAndWhitespace = 1 << 1, /* Ignore whitespace and #-prefixed comments in the pattern. */
NSRegularExpressionIgnoreMetacharacters = 1 << 2, /* Treat the entire pattern as a literal string. */
NSRegularExpressionDotMatchesLineSeparators = 1 << 3, /* Allow . to match any character, including line separators. */
NSRegularExpressionAnchorsMatchLines = 1 << 4, /* Allow ^ and $ to match the start and end of lines. */
NSRegularExpressionUseUnixLineSeparators = 1 << 5, /* Treat only \n as a line separator (otherwise, all standard line separators are used). */
NSRegularExpressionUseUnicodeWordBoundaries = 1 << 6 /* Use Unicode TR#29 to specify word boundaries (otherwise, traditional regular expression word boundaries are used). */
};
对应的值表示的意义:
NSRegularExpressionCaseInsensitive = 1 << 0, // 不区分大小写的
NSRegularExpressionAllowCommentsAndWhitespace = 1 << 1, // 忽略空格和
NSRegularExpressionIgnoreMetacharacters = 1 << 2, // 整体化
NSRegularExpressionDotMatchesLineSeparators = 1 << 3, // 匹配任何字符,包括行分隔符
NSRegularExpressionAnchorsMatchLines = 1 << 4, // 允许^和$在匹配的开始和结束行
NSRegularExpressionUseUnixLineSeparators = 1 << 5, // (查找范围为整个的话无效)
NSRegularExpressionUseUnicodeWordBoundaries = 1 << 6 // (查找范围为整个的话无效)
五、NSNumber Compatible
示例
NSString *str4 = @"1234577045";
long value = [str4 longValue];
NSLog(@"值为 = %ld",value);
实现
- (NSNumber *)numberValue {
return [NSNumber numberWithString:self];
}
最后就是进入NSNumber的分类进行了处理
+ (NSNumber *)numberWithString:(NSString *)string {
NSString *str = [[string stringByTrim] lowercaseString];
if (!str || !str.length) {
return nil;
}
static NSDictionary *dic;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dic = @{@"true" : @(YES),
@"yes" : @(YES),
@"false" : @(NO),
@"no" : @(NO),
@"nil" : [NSNull null],
@"null" : [NSNull null],
@"<null>" : [NSNull null]};
});
id num = dic[str];
if (num) {
if (num == [NSNull null]) return nil;
return num;
}
// hex number
int sign = 0;
if ([str hasPrefix:@"0x"]) sign = 1;
else if ([str hasPrefix:@"-0x"]) sign = -1;
if (sign != 0) {
NSScanner *scan = [NSScanner scannerWithString:str];
unsigned num = -1;
BOOL suc = [scan scanHexInt:&num];
if (suc)
return [NSNumber numberWithLong:((long)num * sign)];
else
return nil;
}
// normal number
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
return [formatter numberFromString:string];
}
六、Utilities
下面我们看一下API接口。
#pragma mark - Utilities
///=============================================================================
/// @name Utilities
///=============================================================================
/**
Returns a new UUID NSString
e.g. "D1178E50-2A4D-4F1F-9BD3-F6AAB00E06B1"
*/
+ (NSString *)stringWithUUID;
/**
Returns a string containing the characters in a given UTF32Char.
@param char32 A UTF-32 character.
@return A new string, or nil if the character is invalid.
*/
+ (nullable NSString *)stringWithUTF32Char:(UTF32Char)char32;
/**
Returns a string containing the characters in a given UTF32Char array.
@param char32 An array of UTF-32 character.
@param length The character count in array.
@return A new string, or nil if an error occurs.
*/
+ (nullable NSString *)stringWithUTF32Chars:(const UTF32Char *)char32 length:(NSUInteger)length;
/**
Enumerates the unicode characters (UTF-32) in the specified range of the string.
@param range The range within the string to enumerate substrings.
@param block The block executed for the enumeration. The block takes four arguments:
char32: The unicode character.
range: The range in receiver. If the range.length is 1, the character is in BMP;
otherwise (range.length is 2) the character is in none-BMP Plane and stored
by a surrogate pair in the receiver.
stop: A reference to a Boolean value that the block can use to stop the enumeration
by setting *stop = YES; it should not touch *stop otherwise.
*/
- (void)enumerateUTF32CharInRange:(NSRange)range usingBlock:(void (^)(UTF32Char char32, NSRange range, BOOL *stop))block;
/**
Trim blank characters (space and newline) in head and tail.
@return the trimmed string.
*/
- (NSString *)stringByTrim;
/**
Add scale modifier to the file name (without path extension),
From @"name" to @"name@2x".
e.g.
<table>
<tr><th>Before </th><th>After(scale:2)</th></tr>
<tr><td>"icon" </td><td>"icon@2x" </td></tr>
<tr><td>"icon " </td><td>"icon @2x" </td></tr>
<tr><td>"icon.top" </td><td>"icon.top@2x" </td></tr>
<tr><td>"/p/name" </td><td>"/p/name@2x" </td></tr>
<tr><td>"/path/" </td><td>"/path/" </td></tr>
</table>
@param scale Resource scale.
@return String by add scale modifier, or just return if it's not end with file name.
*/
- (NSString *)stringByAppendingNameScale:(CGFloat)scale;
/**
Add scale modifier to the file path (with path extension),
From @"name.png" to @"name@2x.png".
e.g.
<table>
<tr><th>Before </th><th>After(scale:2)</th></tr>
<tr><td>"icon.png" </td><td>"icon@2x.png" </td></tr>
<tr><td>"icon..png"</td><td>"icon.@2x.png"</td></tr>
<tr><td>"icon" </td><td>"icon@2x" </td></tr>
<tr><td>"icon " </td><td>"icon @2x" </td></tr>
<tr><td>"icon." </td><td>"icon.@2x" </td></tr>
<tr><td>"/p/name" </td><td>"/p/name@2x" </td></tr>
<tr><td>"/path/" </td><td>"/path/" </td></tr>
</table>
@param scale Resource scale.
@return String by add scale modifier, or just return if it's not end with file name.
*/
- (NSString *)stringByAppendingPathScale:(CGFloat)scale;
/**
Return the path scale.
e.g.
<table>
<tr><th>Path </th><th>Scale </th></tr>
<tr><td>"icon.png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png" </td><td>2 </td></tr>
<tr><td>"icon@2.5x.png" </td><td>2.5 </td></tr>
<tr><td>"icon@2x" </td><td>1 </td></tr>
<tr><td>"icon@2x..png" </td><td>1 </td></tr>
<tr><td>"icon@2x.png/" </td><td>1 </td></tr>
</table>
*/
- (CGFloat)pathScale;
/**
nil, @"", @" ", @"\n" will Returns NO; otherwise Returns YES.
*/
- (BOOL)isNotBlank;
/**
Returns YES if the target string is contained within the receiver.
@param string A string to test the the receiver.
@discussion Apple has implemented this method in iOS8.
*/
- (BOOL)containsString:(NSString *)string;
/**
Returns YES if the target CharacterSet is contained within the receiver.
@param set A character set to test the the receiver.
*/
- (BOOL)containsCharacterSet:(NSCharacterSet *)set;
/**
Try to parse this string and returns an `NSNumber`.
@return Returns an `NSNumber` if parse succeed, or nil if an error occurs.
*/
- (nullable NSNumber *)numberValue;
/**
Returns an NSData using UTF-8 encoding.
*/
- (nullable NSData *)dataValue;
/**
Returns NSMakeRange(0, self.length).
*/
- (NSRange)rangeOfAll;
/**
Returns an NSDictionary/NSArray which is decoded from receiver.
Returns nil if an error occurs.
e.g. NSString: @"{"name":"a","count":2}" => NSDictionary: @[@"name":@"a",@"count":@2]
*/
- (nullable id)jsonValueDecoded;
/**
Create a string from the file in main bundle (similar to [UIImage imageNamed:]).
@param name The file name (in main bundle).
@return A new string create from the file in UTF-8 character encoding.
*/
+ (nullable NSString *)stringNamed:(NSString *)name;
1. + (NSString *)stringWithUUID;
该方法返回的是UUID字符串。
示例调用
NSString *resultStr = [NSString stringWithUUID];
NSLog(@"UUID为 = %@", resultStr);
输出结果
2023-04-03 14:56:14.138679+0800 YYKitDemo[2210:3962979] UUID为 = F2F21473-6B4A-4C0C-9574-7DB7DFE3E272
方法实现
+ (NSString *)stringWithUUID {
CFUUIDRef uuid = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, uuid);
CFRelease(uuid);
return (__bridge_transfer NSString *)string;
}
2. + (nullable NSString *)stringWithUTF32Char:(UTF32Char)char32;
该方法的作用就是将给定的UTF32Char类型的字符转化为一个NSString类型的字符串,如果这个字符是无效的,那么转化的字符串为nil。
示例调用
UTF32Char number = 97;
NSString *resultStr1 = [NSString stringWithUTF32Char:number];
NSLog(@"resultStr = %@", resultStr1);
输出结果:
2023-04-03 14:58:03.797956+0800 YYKitDemo[2268:3966023] resultStr = a
方法实现
+ (NSString *)stringWithUTF32Char:(UTF32Char)char32 {
char32 = NSSwapHostIntToLittle(char32);
return [[NSString alloc] initWithBytes:&char32 length:4 encoding:NSUTF32LittleEndianStringEncoding];
}
上面方法的实现中调用的两个方法均为系统内部的方法。
3. + (nullable NSString *)stringWithUTF32Chars:(const UTF32Char *)char32 length:(NSUInteger)length;
该方法的作用就是根据给定的 UTF-32字符组和长度,返回一个字符串。
示例调用
UTF32Char test = 98;
NSString *resultStr2 = [NSString stringWithUTF32Chars:&test length:1];
NSLog(@"resultStr = %@", resultStr2);
打印结果
2023-04-03 15:02:26.808306+0800 YYKitDemo[2425:3973674] resultStr = b
方法实现
+ (NSString *)stringWithUTF32Chars:(const UTF32Char *)char32 length:(NSUInteger)length {
return [[NSString alloc] initWithBytes:(const void *)char32
length:length * 4
encoding:NSUTF32LittleEndianStringEncoding];
}
4. - (void)enumerateUTF32CharInRange:(NSRange)range usingBlock:(void (^)(UTF32Char char32, NSRange range, BOOL *stop))block;
枚举字符串指定范围内的Unicode字符(UTF-32),这里需要说明下几个参数:
- range :字符串在range范围内遍历子字符串。
- block :执行遍历的块。
- char32 : unicode字符
- range :这个是接收者,如果range.length == 1,字符是BMP;否则(range.length == 2),该字符在非BMP平面中,并由代理对存储在接收器中。
- stop : 一个布尔值的引用,块可以通过设置* stop = YES来停止遍历。
示例调用
NSString *str5 = @"abdsdfda";
[str5 enumerateUTF32CharInRange:NSMakeRange(0, 3) usingBlock:^(UTF32Char char32, NSRange range, BOOL * _Nonnull stop) {
NSLog(@"字符是 %d",char32);
}];
打印结果
2023-04-03 15:10:40.178462+0800 YYKitDemo[2638:3983694] 字符是 97
2023-04-03 15:10:40.178535+0800 YYKitDemo[2638:3983694] 字符是 98
2023-04-03 15:10:40.178617+0800 YYKitDemo[2638:3983694] 字符是 100
下面看一下该方法的实现
- (void)enumerateUTF32CharInRange:(NSRange)range usingBlock:(void (^)(UTF32Char char32, NSRange range, BOOL *stop))block {
NSString *str = self;
if (range.location != 0 || range.length != self.length) {
str = [self substringWithRange:range];
}
NSUInteger len = [str lengthOfBytesUsingEncoding:NSUTF32StringEncoding] / 4;
UTF32Char *char32 = (UTF32Char *)[str cStringUsingEncoding:NSUTF32LittleEndianStringEncoding];
if (len == 0 || char32 == NULL) return;
NSUInteger location = 0;
BOOL stop = NO;
NSRange subRange;
UTF32Char oneChar;
for (NSUInteger i = 0; i < len; i++) {
oneChar = char32[i];
subRange = NSMakeRange(location, oneChar > 0xFFFF ? 2 : 1);
block(oneChar, subRange, &stop);
if (stop) return;
location += subRange.length;
}
}
5. - (NSString *)stringByTrim;
该方法的作用就是修剪头部和尾部的空白字符(空格和换行符)。
6. - (NSString *)stringByAppendingNameScale:(CGFloat)scale;
其实,就是实现类似@"name" 到 @"name@2x"这样的功能。
7. - (NSString *)stringByAppendingPathScale:(CGFloat)scale;
其实就是实现从@"name.png" 到 @"name@2x.png"这样的类似转化。
8. - (CGFloat)pathScale;
9. - (BOOL)isNotBlank;
该方法的作用就是用来判断是否是空白。nil, @"", @" ", @"\n"会返回NO,其他返回YES。
10. - (BOOL)containsString:(NSString *)string;
这个方法很好理解,就是判断一个字符串是否包含另外一个字符串。
11. - (BOOL)containsCharacterSet:(NSCharacterSet *)set;
这个方法的作用就是字符串是否包含某个字符。
12. - (nullable NSNumber *)numberValue;
这个方法就是将字符串转化为NSNumber数据类型,如果不能转换,就返回nil。
13. - (nullable NSData *)dataValue;
这个方法就是将字符串转化为NSData数据类型,使用的是UTF - 8编码。
14. - (NSRange)rangeOfAll;
这个方法就是将返回字符串的range - NSMakeRange(0, self.length)。
15. - (nullable id)jsonValueDecoded;
该方法的作用就是将指定的Json字符串转化为字典或者数组。
16. + (nullable NSString *)stringNamed:(NSString *)name;
该方法的作用就是从main bundle文件中创建字符串,类似于[UIImage imageNamed:]。返回值为文件中UTF - 8编码的字符串。找不到则返回null