旧iOS应用UIWebView无法唤起其他App URL,Safari可正常打开求助
嘿,咱们来搞定你遇到的这个UIWebView打不开第三方App URL的问题——结合2016年突然失效的时间点,这十有八九是iOS 9当年引入的LSApplicationQueriesSchemes限制搞的鬼。苹果从iOS 9开始要求App必须显式声明它要调用的其他App的URL Scheme,不然系统会直接拦截这类跳转;而Safari作为系统浏览器不受这个规则约束,所以直接在Safari里就能正常唤起。
下面给你一步步拆解排查和修复的方法:
1. 先确认目标App的URL Scheme
首先找到那个用来唤起打印标签App的完整URL(比如类似printlabel://print?data=xxx这样的),把开头的printlabel部分提取出来,这就是目标App的URL Scheme,咱们后面要用到它。
2. 在Info.plist里添加Scheme白名单
打开项目里的Info.plist文件,添加一个名为LSApplicationQueriesSchemes的数组类型键,然后把刚才提取的URL Scheme作为字符串元素加进去:
<key>LSApplicationQueriesSchemes</key> <array> <string>printlabel</string> <!-- 替换成你实际的URL Scheme --> </array>
如果之后还要唤起其他App,直接在这个数组里加对应的Scheme就行。
3. 检查UIWebView的代理拦截逻辑
有时候UIWebView的UIWebViewDelegate代理方法webView:shouldStartLoadWithRequest:navigationType:会被用来拦截请求,你得看看这里是不是有逻辑阻止了这类URL的跳转。可以改成这样:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *targetURL = request.URL; // 判断是不是目标App的URL Scheme if ([targetURL.scheme isEqualToString:@"printlabel"]) { // 手动唤起目标App [[UIApplication sharedApplication] openURL:targetURL options:@{} completionHandler:nil]; // 返回NO,不让UIWebView尝试加载这个它处理不了的URL return NO; } // 其他正常的网页请求允许加载 return YES; }
注意:iOS 10之后推荐用openURL:options:completionHandler:,如果你的App还要兼容iOS 9,也可以保留旧的openURL:写法,但前者是更规范的选择。
4. 额外验证:检查目标App是否已安装
你还可以在代码里先判断目标App能不能被唤起,避免出现无意义的错误提示:
NSURL *printAppURL = [NSURL URLWithString:@"printlabel://"]; if ([[UIApplication sharedApplication] canOpenURL:printAppURL]) { [[UIApplication sharedApplication] openURL:printAppURL options:@{} completionHandler:nil]; } else { // 这里可以给用户弹个提示,说打印App没安装 NSLog(@"打印标签的App未安装,请先安装"); }
不过要注意,iOS 9之后canOpenURL:也需要依赖刚才在Info.plist里添加的白名单,不然会直接返回NO。
5. 排查ATS的影响(可选)
如果你的跳转是通过HTTPS链接重定向到URL Scheme的,那iOS 9的ATS(App Transport Security)可能也会有影响,但这种情况比较少见。要是前面的步骤都没解决问题,再去检查Info.plist里的ATS设置,不过优先处理LSApplicationQueriesSchemes的问题就好。
总的来说,最核心的原因就是iOS 9开始的Scheme白名单要求,先把这个加上,再检查代理拦截逻辑,应该就能解决“URL cannot be shown”的报错了。
内容的提问来源于stack exchange,提问作者BearP

