YYKit 源码探究 NSString+YYAdd(一)

前言

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的基本框架。


WeChat49c9ea940bac96a3e0f1e82e270c3a99.png
image.png

image.png

image.png

image.png

NSString+YYAdd 框架

基本结构

下面我们来看下NSString分类 NSString+YYAdd 的架构,如下图所示


image.png

其实这里面包含了六个部分:

  • 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}
方法的实现
image.png

这里其实还是利用NSString的原生方法

boundingRectWithSize: options: attributes: context:

其他方法同理

例如:

- (CGFloat)widthForFont:(UIFont *)font;
image.png

此处传入的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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容