stringByAddingPercentEncodingWithAllowedCharacters方法解析

今天做域名加签校验遇到一个问题,就是请求地址编码问题,url地址如下:
NSString *tmpUrlString = @"https://www.baidu.com/devtest-news/app/news/keyword/recommend?keyword=土甲,巴利基斯,萨姆桑斯堡&test=你好*2";,这里需要对参数里面的中文",","*"等进行转义。

由于之前对NSCharacterSetstringByAddingPercentEncodingWithAllowedCharacters方法没有细致了解,因此这里做了下笔记.

DEMO详见

一. NSCharacterSet

1.API解释

/** 001 根据一个给定的字符串获取一个NSCharacterSet对象 */
+ (NSCharacterSet *)characterSetWithCharactersInString:(NSString *)aString;

/** 002 相反字符串限制 【具体见接下的例子】 */
@property (readonly, copy) NSCharacterSet *invertedSet;

举个例子:

    // 0 - 9字符集
    NSString *numberStr = @"0123456789";
    NSCharacterSet *numberSet = [NSCharacterSet characterSetWithCharactersInString:numberStr];
    NSString *str = @"7chinafjf78990love";
    // 过滤str字符串里面的0-9内的字符
    NSLog(@"numberSet----%@",[[str componentsSeparatedByCharactersInSet:numberSet] componentsJoinedByString:@""]);
    
    // 保留str字符串里面的0-9内的字符
    NSCharacterSet *invertedSet = [[NSCharacterSet characterSetWithCharactersInString:numberStr] invertedSet];
    NSLog(@"invertedSet----%@",[[str componentsSeparatedByCharactersInSet:invertedSet] componentsJoinedByString:@""]);

输出日志:

2021-01-02 16:08:02.239695+0800 FJFBlogDemo[13342:636161] numberSet----chinafjflove
2021-01-02 16:08:02.239784+0800 FJFBlogDemo[13342:636161] invertedSet----778990

2.常用快捷方法合集

[NSCharacterSet alphanumericCharacterSet];          //所有数字和字母(大小写)  
[NSCharacterSet decimalDigitCharacterSet];          //0-9的数字  
[NSCharacterSet letterCharacterSet];                //所有字母  
[NSCharacterSet lowercaseLetterCharacterSet];       //小写字母  
[NSCharacterSet uppercaseLetterCharacterSet];       //大写字母  
[NSCharacterSet punctuationCharacterSet];           //标点符号  
[NSCharacterSet whitespaceAndNewlineCharacterSet];  //空格和换行符  
[NSCharacterSet whitespaceCharacterSet];            //空格  

stringByAddingPercentEncodingWithAllowedCharacters方法

所以这两个函数可以解释如下:

// 对除了这些特殊字符(!$&'()*+-./:;=?@_~%#[])以外的所有字符进行编码
+ (NSString *)fjf_encodeSpecialCharacterWithUrlString:(NSString *)urlString {
    return [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet   characterSetWithCharactersInString:@"!$&'()*+-./:;=?@_~%#[]"]];
}

// 只编码 中文 字符(对所有字符都不进行编码,除了中文)
+ (NSString *)fjf_encodeChineseCharacterWithUrlString:(NSString *)urlString {
    return  [urlString stringByAddingPercentEncodingWithAllowedCharacters:[[NSCharacterSet characterSetWithCharactersInString:@""] invertedSet]];
}

对url统一处理方法

+ (NSString *)fjf_encodeUrlStringWithString:(NSString *)urlString {

   //先截取问号
   NSArray *allElements = [urlString componentsSeparatedByString:@"?"];
   NSMutableDictionary *params = [NSMutableDictionary dictionary];//待set的参数字典
   if (allElements.count == 2) {
      //有参数或者?后面为空
       NSString *myUrlString = allElements[0];
       NSString *paramsString = allElements[1];

       //获取参数对
       NSArray *paramsArray = [paramsString componentsSeparatedByString:@"&"];
       if (paramsArray.count >= 2) {
          for (NSInteger i = 0; i < paramsArray.count; i++) {
             NSString *singleParamString = paramsArray[i];
             NSArray *singleParamSet = [singleParamString componentsSeparatedByString:@"="];
             if (singleParamSet.count == 2) {
                 NSString *key = singleParamSet[0];
                 NSString *value = singleParamSet[1];
                 if (key.length > 0 || value.length > 0) {
                    [params setObject:[self fjf_percentEscapedStringWithString:value]  forKey:[self fjf_percentEscapedStringWithString:key]];
                 }
             }
          }
       } else if (paramsArray.count == 1) {
          //无 &。url只有?后一个参数
          NSString *singleParamString = paramsArray[0];
          NSArray *singleParamSet = [singleParamString componentsSeparatedByString:@"="];
          if (singleParamSet.count == 2) {
             NSString *key = singleParamSet[0];
             NSString *value = singleParamSet[1];
             if (key.length || value.length) {
                 [params setObject:[self fjf_percentEscapedStringWithString:value] forKey:[self fjf_percentEscapedStringWithString:key]];
             }
          }
       }
      //整合url及参数
       NSMutableString *tmpMstring = [NSMutableString stringWithString:myUrlString];
       [params enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
           [tmpMstring appendString:[self fjf_urlSymbolWithUrl:tmpMstring]];
           [tmpMstring appendString:[NSString stringWithFormat:@"%@=%@", key, obj]];
       }];
       return tmpMstring;
   }
    return urlString;
}


+ (NSString *)fjf_percentEscapedStringWithString:(NSString *)string {
    NSString * kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
    NSString * kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;=";

    NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]];

    // FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028
    // return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];

    static NSUInteger const batchSize = 50;

    NSUInteger index = 0;
    NSMutableString *escaped = @"".mutableCopy;

    while (index < string.length) {
        NSUInteger length = MIN(string.length - index, batchSize);
        NSRange range = NSMakeRange(index, length);

        // To avoid breaking up character sequences such as 
        range = [string rangeOfComposedCharacterSequencesForRange:range];

        NSString *substring = [string substringWithRange:range];
        NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
        [escaped appendString:encoded];

        index += range.length;
    }
    return escaped;
}


// 请求地址 拼接 符号
+ (NSString *)fjf_urlSymbolWithUrl:(NSString *)url {
    NSString *symbolString = @"?";
    if ([url containsString:@"?"]) {
        symbolString = @"&";
    }
    return symbolString;
}

你可能感兴趣的:(stringByAddingPercentEncodingWithAllowedCharacters方法解析)