http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
如上URL,其基本构成
scheme: http
host:www.aspxfans.com
port:8080
path:/news/index.asp
query:boardID=5&ID=24618&page=1
fragment:name
可见,一般情况下,?后面的是a=b的样式是query,而#后面是fragment。(这句话有毛病,后面我们再说)
query是用于传递参数,一般为key-value的形式,而fragment的作用在这篇文章中有详细的介绍:
https://www.jianshu.com/p/2c07fbb52b45
一言以蔽之:fragment有很多取巧的特性。我们上述未考虑fragment的情况的参数拼接,实际上会破坏fragment的机制。导致跳转异常。
如何正确的给URL拼接参数:
答案是根据url的标准来。
如上分享,url的组成是固定的,原生给url拼接参数本身是为了在请求时把一对key-value带过去,所以,拼接的元素应该是query,而非其他。那么,如何正确的拼接参数到query呢?很多时候,我们会用上述的想法,在?#上做文章。但是url实在太灵活了。我们依据某些特征的分割总会有问题。比如我们用?来分割下面的url:
https://www.baidu.com/#?a=b
很遗憾,这里的a=b虽然看起来很像参数,应该属于query,但是实际上它却属于fragment。
所以,我们就不要自己动这种歪脑筋了。各种系统都有系统方法帮我们分解url,然后合成url。以OC为例,拼接query的代码如下:
NSURLComponents *components = [NSURLComponents componentsWithString:url];
NSString *query = components.query;
NSString *tmpQuery = @"a=b";
query = (query&&![query isEqualToString:@""])? [query stringByAppendingString:[NSString stringWithFormat:@"&%@",tmpQuery]] : tmpQuery;
components.query = query;
NSString *resulturl = components.URL.absoluteString;
以上使用了NSURLComponents类来分解原url,然后把新的参数拼接到query中,再生成新的url,简单明了!
-------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------
人生在世,少立flag啊!
前面提到了我们使用NSURLComponents成功实现了按照url的标准添加了参数。业务上线两个版本,突然有业务反馈,他们的url被过度decode了。
问题的排查很艰辛:业务反馈重装App是没有问题的,只有升级的用户才有问题。我们排查从两个方面入手:第一、对比升级前后的差异,这部分浪费的时间太多;第二、排查显式的decode的地方。后来猛然想到我们新增上述参数是有条件的,是不是被这个参数搞的,随即将条件调整到满足添加参数的条件,成功复现问题。
坑爹的 NSURLComponents 会默认对url做一次decode!!!特此Mark!!!!
--------------------------------------------------------------------------------------------
问题的解决:
以上问题会让我们产生一个直觉:苹果真的这么愚蠢吗?设计出这么渣的API。但是事实是,苹果还有一个API不会decode url------------------percentEncodedQuery.当前还有与它对应的好几个兄弟。它可以保留被encode过的部分。以此替换前面的query就没有问题了。
教训:仔细看文档!!!!!!!!!!!!!!!!!!
经过上面的分析,我们对编码有了一定了解,那么像'()*+,-.等几个特殊字符,并不支持编码,和其他平台传输有乱码现象怎么办呢?这个时候就需要自定义字符集了。<=>?//编码后encode: %20!%3C=%3E?变量为什么要反转集合呢?因为入参的字符集合是不会被编码的集合,我们反转之后就是对我们自定义的变量里面的字符进行编码了。End。
- (NSString *)LDURLEncodedString :(NSString*)str{
CFStringRef strRef = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR("!*'();:@
NSString* encodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
Swift:
let encodedString = urlString.addingPercentEscapes(using: .utf8)
此方...
有两种方法:
一,使用NSString的方法:
NSString* string2 = [string1 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding
这里有一个直观的描述来解释什么是“一维数据类型”:number或string被格式化为多种多样的值,可以通过数学运算或某种转换方法可以算出它们的值。比如:十六进制的颜色值#EE8262的红绿蓝三原色的值通过掩码或移位运算得出;正则表达式可以通过少量字符中复杂的样本中进行匹配。
在所...
[UIApplication sharedApplication].idleTimerDisabled = YES;
2、隐藏某行cell
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndex...
NSURLComponents *components = [[NSURLComponents alloc] initWithString:url];
[components.queryItems enumerateObjectsUsingBlock:^(NSURLQueryItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnu...
在日常的编程工作中,经常需要拼接URL字符串,可能直接写成如下的形式:
NSString *urlStr = @"https://www.demo.com/query?name=Jack";
复制代码对于比较简短的url字符串,这种写法直观方便。但是如果需要拼接一大串的query语句的话,就会非常地长(虽然Objective-C语法本身也是非常的长),譬如:
NSString *urlStr = ...