1 问题描述
- NSURL通过方法
- (instancetype)initWithString:(NSString *)URLString
实例化时返回nil
例如下面的UrlString:
http://image.myutopa.com/FrPk4GvZZRp7LqbxVNYPNnboLy-F?imageView2/1/w/80/h/80/q/75|imageslim&e=1562228012&token=WNtUYaMiCdpTDzanlE03SjKXLinbmTzkLGXEBYC_:6dc5rTdvO95Ed4yO8mUGw6Dia8w=
使用NSURL编码时返回的就是nil
2 问题产生场景
- 该图片是存放在七牛中的,后台获取地址时给图片添加了裁剪的样式,最后返回到前端的图片地址如上。
- 而问题地址则是用于分享功能,项目中使用MOB的ShareSDK第三方分享组件
- 执行分享时,会调用如下代码
NSMutableDictionary *shareParams = [NSMutableDictionary dictionary];
[shareParams SSDKSetupShareParamsByText:content
images:Images
url:[NSURL URLWithString:urlStr]
title:title
type:SSDKContentTypeAuto]; //qq如果没有title和content只有默认图片和URL时,执行的是分享图片。最少有Title时候分享类型为URL网页分享
//进行分享
[ShareSDK share:[self switchGTSharePlatformType:sharePlatformType] //传入分享的平台类型
parameters:shareParams
onStateChanged:^(SSDKResponseState state, NSDictionary *userData, SSDKContentEntity *contentEntity, NSError *error) {
// 回调处理....
NSLog(@"\n\n分享回调 - %ld, %@, %@, %@\n\n",state, userData, contentEntity, error);
}
}];
其中,images 这个字符串数组就是存放分享图片的地址的。
- 当方法
SSDKSetupShareParamsByText:images:url:title:type:
处理图片数组时,会将字符串地址转为 NSURL 对象。 - 而因为地址是有问题的,所以 images 处理后得到的是空的 NSURL 对象数组,导致分享失败
3 问题定位(为什么地址在浏览器中可以获取到,使用NSURL 实例方法则返回 nil?)
3.1 参考 API 文档描述
initWithString: - NSURL | Apple Developer Documentation
上图重点如下:
- URLString 参数不能为空
- URLString 参数的值必须满足 RFC 2396 协议中定义的URL格式,可参考RFC 3986 - Uniform Resource Identifier (URI): Generic Syntax
3.2 问题原因
综上,URLString中应除了下述字符外的其他字符都需要进行百分号转义(percent-escaped)
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
| 符号 导致 URLString 不符合要求对比问题URLString,发现地址中有
|
符号不符合要求
4 解决方法
- 生产环境上,优先让后台不返回裁剪样式的 URLString,毕竟分享后都会对大图进行裁剪
- 后续使用 hardcode 对该类型地址进行 percent-escaped 百分号编码,杜绝后患
[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- 就本次业务逻辑hardcode
//使用ShareSDK分享
+ (void)sharePlatformType:(GTSharePlatformType)sharePlatformType title:(NSString *)title content:(NSString *)content urlStr:(NSString *)urlStr images:(NSArray *)images onStateChanged:(GTShareStateChangedHandler)stateChangedHandler {
//1、创建分享参数
// 对复杂的string url地址进行编码
NSMutableArray *freshImages = [NSMutableArray array];
[images enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:[NSString class]]) {
NSString *obj1 = (NSString *)obj;
NSString *fixedStr = [obj1 stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[freshImages addObject:fixedStr];
}
}];
if (!freshImages.count) {
freshImages = [NSMutableArray arrayWithArray:@[[UIImage imageNamed:@"login_icon_logo"]]];
}
NSMutableDictionary *shareParams = [NSMutableDictionary dictionary];
[shareParams SSDKSetupShareParamsByText:content
images:freshImages
url:[NSURL URLWithString:urlStr]
title:title
type:SSDKContentTypeAuto]; //qq如果没有title和content只有默认图片和URL时,执行的是分享图片。最少有Title时候分享类型为URL网页分享
//进行分享
[ShareSDK share:[self switchGTSharePlatformType:sharePlatformType] //传入分享的平台类型
parameters:shareParams
onStateChanged:^(SSDKResponseState state, NSDictionary *userData, SSDKContentEntity *contentEntity, NSError *error) {
// 回调处理....
NSLog(@"\n\n分享回调 - %ld, %@, %@, %@\n\n",state, userData, contentEntity, error);
if (stateChangedHandler) {
GTShareResponseState gtResponseState = [self switchSSDKResponseState:state];
stateChangedHandler(gtResponseState, userData, contentEntity, error);
}
}];
}
网友评论