iOS openURL调用失败

今天改代码的时候,遇到一个问题,在APP内部跳转到Safari打开某个链接的时候,竟然报错了。然后经过一番试错,终于找到了问题所在!记录一下,以备以后方便查找!

先贴上源代码:

/**
 * 调用Safari加载URL
 */
- (void)openScheme:(NSString *)urlString {
    UIApplication *application = [UIApplication sharedApplication];
    NSURL *URL = [NSURL URLWithString:urlString];
    
    if ([application respondsToSelector:@selector(openURL:options:completionHandler:)]) {
        [application openURL:URL options:@{} completionHandler:^(BOOL success) {
            LOG(@"Open %@: %d",urlString,success);
        }];
    } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        //过期的方法
        BOOL success = [application openURL:URL];
#pragma clang diagnostic pop
        LOG(@"Open %@: %d",urlString,success);
    }
}

传入的参数为:www.gsfxuk.cn/index.html
从逻辑来看,没什么问题,而且最奇怪的,在另外一个项目中,同样的代码,是没有问题的。

这里罗列一下思考是几个方面:

  1. URL问题
    打断点看了一下生成的URL,是有值的。排除!
    引申:

    以前遇到一个问题:
    后台在录入数据的时候,手滑在URL的结尾多加了一个空格,eg: www.baidu.com ,
    就因为这个空格,就会造成无法生成正确的URL对象。(NSURL对象为nil)
    

    应对此种问题的解决方法:

    NSString *validStr = [transferStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    

    此时得到的validStr即为不带空格的字符串!

  2. 新方法存在不兼容问题
    根据苹果的习惯,新方法是有版本要求的,但是出了新方法之后,老的方法也是一样可行的,所以我就先调用一下老的方法,排除一下。结果!不行!排除此猜想

  3. 方法传参问题
    接着看一下新方法的入参,即多了的那个options
    该参数解释如下:引用自iOS10 新变化之废弃的 openURL

    options目前可传入参数Key在UIApplication头文件只有一个:UIApplicationOpenURLOptionUniversalLinksOnly,其对应的Value为布尔值,默认为False.如该Key对应的Value为True,那么打开所传入的Universal Link时,只允许通过这个Link所代表的iOS应用跳转的方式打开这个链接,否则就会返回success为false,也就是说只有安装了Link所对应的App的情况下才能打开这个Universal Link,而不是通过启动Safari方式打开这个Link的代表的网站.

    一句话总结一下:
    如果传一个空字典的情况(即不传此值,也即默认值),如果传入的scheme在本地能查询的到,调用本地APP,如果本地匹配不到,则调用Safari打开。
    如果传入的不是一个空字典(即@{UIApplicationOpenURLOptionUniversalLinksOnly: @YES}),此时当且仅当URL有效、且本地装了对应APP的时候,才能打开。(本人猜测是要直接用APP调起某个模块的时候这么写)<本人没遇到过这种情况,所以无法验证,如果说错,请各位大佬批评指正!谢谢!!>

    说到scheme,就必须介绍一下苹果的这个应用间跳转的技术了,见引申1

引申

  1. scheme 摘自-简书谦言忘语
什么是URL Schemes?

URL Schemes是苹果给出的用来跳转到系统应用或者跳转到别人的应用的一种机制。同时还可以在应用之间传数据。

通过对比网页链接来理解 iOS 上的 URL Schemes,应该就容易多了。
URL Schemes 有两个单词:
*URL,我们都很清楚,http://www.apple.com
就是个 URL,我们也叫它链接或网址;
*Schemes,表示的是一个 URL 中的一个位置——最初始的位置,即 ://
之前的那段字符。比如 http://www.apple.com
这个网址的 Schemes是 http
根据我们上面对 URL Schemes 的使用,我们可以很轻易地理解,在以本地应用为主的 iOS 上,我们可以像定位一个网页一样,用一种特殊的 URL 来定位一个应用甚至应用里某个具体的功能。而定位这个应用的,就应该是这个应用的 URL 的 Schemes 部分,也就是开头儿那部分。


我们在项目的info->URL Types中设置自己的URL Schemes,就等于是在手机中注册了一个域名,然后别的应用或者Safari,WKWebview组件就可以通过访问该scheme已达到调起APP的作用。
以下写出调起APP的代码:

    NSURL *url = [NSURL URLWithString:@"weixin://"];
    [[UIApplication sharedApplication]openURL:url options:@{} completionHandler:^(BOOL success) {
        NSLog(@"success:%@",@(success));
    }];

这么写之后,项目中就会提示是否要打开微信APP
这里也可以理解友盟等第三方登录分享之类的,是在后台配置了应用的独立标识,然后让开发者手动配置在要集成的项目scheme这里,已达到监控统计调起应用,然后再返回的功能。

但是思考一点:

如果我们又在手机上安装了一个APP,其中配置了相同的weixinscheme,此时会怎么跳转呢?

暂无确定结果!

但是可以确定的是:不同的项目是可以有相同的scheme的。
此时,我们可以在调用openURL方法之前,加一个逻辑完善:
-canOpenURL, 即先判断是否能打开,然后再执行!

因此,这里也排除了scheme的配置问题。

  1. 因为刚刚思考了scheme的问题,然后想到了类似域名的解释。然后此时灵光一闪:刚刚的入参为www.gsfxuk.cn/index.html,并没有http://或者https://,那么此时传给Safari的时候,它肯定也不知道是个外链啊!!然后我又在别的项目中打印了URL,看到都是包含http://或者https://的。
    至此,问题定位完成!!

解决:

定位好问题之后,就好解决了。我们只需要判断下传入的URL连接是否包含http://https://,如果不包含,则给它添加上即可!!

/**
 * 把string转换成可以URL跳转的类型(指的是带HTTP或者HTTPS)
 */
- (NSString *)convertToURLFormatWithString:(NSString *)str {
    if ([str containsString:@"http"] || [str containsString:@"https"]) {
        return str;
    }else {
        NSMutableString *strM = [NSMutableString stringWithString:str];
        [strM insertString:@"http://" atIndex:0];
        return strM.copy;
    }
}

参考

Support Universal Links
Querying URL Schemes with canOpenURL
uiapplicationopenurloptionuniversallinksonly参数解释
openURL: deprecated in iOS 10
How can I programmatically determine if a URL is a Universal Link or just a regular web URL?

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