美文网首页
小技巧 - NSURL遇上不规范的URLString

小技巧 - NSURL遇上不规范的URLString

作者: Jacob_LJ | 来源:发表于2018-07-10 21:48 被阅读45次
    小技巧

    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

    NSURL
    上图重点如下:
    1. URLString 参数不能为空
    2. 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);
             }
             
         }];
    }
    

    5 参考

    相关文章

      网友评论

          本文标题:小技巧 - NSURL遇上不规范的URLString

          本文链接:https://www.haomeiwen.com/subject/zlbtpftx.html