I recently found that my UIWebView was choking on ITMS links. Specifically, from the UIWebView in my app, if I navigate to a site such as this one and click the "Available on the App Store" link, UIWebView would error out with "Error Domain=WebKitErrorDomain Code=101 The URL can't be shown."
我最近发现我的UIWebView被ITMS链接堵塞了。具体地说,在我的app的UIWebView中,如果我导航到像这个网站,点击“app Store上的可用”链接,UIWebView就会出现“error Domain=WebKitErrorDomain Code=101”URL无法显示。
After a bit of Googling, I realized that I needed to catch requests for app links and have iOS handle them. I started out by looking to see if the scheme starts with "itms" in -webView:shouldStartLoadWithRequest:navigationType:
, but realized that there might be other kinds of app links that the system can handle. So I came up with this, instead:
用谷歌搜索了一会儿之后,我意识到我需要捕捉应用程序链接的请求,并让iOS来处理它们。我开始查看这个方案是否以webview:shouldStartLoadWithRequest:navigationType:中的“itms”开头,但我意识到系统可能还有其他类型的应用链接可以处理。所以我想到了这个,
- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error {
// Give iOS a chance to open it.
NSURL *url = [NSURL URLWithString:[error.userInfo objectForKey:@"NSErrorFailingURLStringKey"]];
if ([error.domain isEqual:@"WebKitErrorDomain"]
&& error.code == 101
&& [[UIApplication sharedApplication]canOpenURL:url])
{
[[UIApplication sharedApplication]openURL:url];
return;
}
// Normal error handling…
}
I have two questions about this:
我有两个问题:
- Is this sane? I'm specifically checking for the error domain and error code and fetching the URL string from the userInfo. Is that stuff likely to remain?
- 这是理智的吗?我特别检查错误域和错误代码,并从userInfo获取URL字符串。这些东西还会存在吗?
- This does work for the above-linked app store link, but when I switch back to my app, there appears to have been a subsequent failed request that failed with "Frame load interrupted". how can I get rid of that? It doesn't happen when I have the OS handle the request from
-webView:shouldStartLoadWithRequest:navigationType:
, so it's a bit annoying. - 这对于上面链接的app store链接来说是可行的,但是当我切换回我的app时,似乎有一个后续请求失败了,并且“帧加载被中断”。我怎么才能摆脱它呢?当我让操作系统处理来自-webView:shouldStartLoadWithRequest:navigationType:的请求时不会发生这种情况,所以这有点烦人。
How do you handle such requests?
你如何处理这样的请求?
3 个解决方案
#1
89
Here's what I came up with. In webView:shouldStartLoadWithRequest:navigationType:
, I ask the OS to handle any non-http and non-https requests that it can, like so:
这是我想到的。在webView中:shouldStartLoadWithRequest:navigationType:,我要求操作系统处理它能处理的任何非http和非https请求,如下所示:
- (BOOL)webView:(UIWebView *)wv shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
// Determine if we want the system to handle it.
NSURL *url = request.URL;
if (![url.scheme isEqual:@"http"] && ![url.scheme isEqual:@"https"]) {
if ([[UIApplication sharedApplication]canOpenURL:url]) {
[[UIApplication sharedApplication]openURL:url];
return NO;
}
}
return YES;
}
This works very well except for the bloody "Frame Load Interrupted" error. I had thought that by returning false from webView:shouldStartLoadWithRequest:navigationType:
that the web view would not load the request and therefore there would be no errors to handle. But even though I return NO
above, I still "Frame Load Interrupted" error. Why is that?
除了该死的“帧加载被中断”错误之外,这一方法非常有效。我认为通过从webView返回false:shouldStartLoadWithRequest:navigationType: web视图不会加载请求,因此不会有错误需要处理。但是即使我返回NO上面,我仍然“帧加载中断”错误。这是为什么呢?
Anyway, I'm assuming it can be ignored in -webView:didFailLoadWithError:
:
无论如何,我假设它可以在-webView中被忽略:didFailLoadWithError:
- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error {
// Ignore NSURLErrorDomain error -999.
if (error.code == NSURLErrorCancelled) return;
// Ignore "Fame Load Interrupted" errors. Seen after app store links.
if (error.code == 102 && [error.domain isEqual:@"WebKitErrorDomain"]) return;
// Normal error handling…
}
And now iTunes URLs work properly, as do mailto:
s and app links.
现在iTunes url可以正常工作了,mailto:s和app链接也是如此。
#2
8
Starting with Theory's code, examine the URL for "itms" scheme(s) (this method can be called multiple times due to redirects). Once you see an "itms" scheme, stop the webView from loading and open the URL with Safari. My WebView happens to be in a NavigationController, so I pop out of that after opening Safari (less flashing).
从Theory的代码开始,检查“itms”方案的URL(由于重定向,可以多次调用此方法)。一旦您看到“itms”方案,请停止webView的加载并使用Safari打开URL。我的WebView碰巧是在一个NavigationController中,所以我在打开Safari(少闪烁)之后就跳出来了。
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request
navigationType:(UIWebViewNavigationType)navigationType
{
if ([[[request URL] scheme] isEqualToString:@"itms-apps"]) {
[webView stopLoading];
[[UIApplication sharedApplication] openURL:[request URL]];
[self.navigationController popViewControllerAnimated:YES];
return NO;
} else {
return YES;
}
}
#3
-2
Does it help if you register your app for handling itms: links?
如果你注册你的应用来处理itms:链接,会有帮助吗?
e.g. http://inchoo.net/iphone-development/launching-application-via-url-scheme/
例如,http://inchoo.net/iphone-development/launching-application-via-url-scheme/
You may start with scheme http
but then get an itms
redirect, which could fail if your app is not registered as handling that scheme.
您可以从scheme http开始,然后获得itms重定向,如果您的应用程序没有注册为处理该方案,那么它可能会失败。
#1
89
Here's what I came up with. In webView:shouldStartLoadWithRequest:navigationType:
, I ask the OS to handle any non-http and non-https requests that it can, like so:
这是我想到的。在webView中:shouldStartLoadWithRequest:navigationType:,我要求操作系统处理它能处理的任何非http和非https请求,如下所示:
- (BOOL)webView:(UIWebView *)wv shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
// Determine if we want the system to handle it.
NSURL *url = request.URL;
if (![url.scheme isEqual:@"http"] && ![url.scheme isEqual:@"https"]) {
if ([[UIApplication sharedApplication]canOpenURL:url]) {
[[UIApplication sharedApplication]openURL:url];
return NO;
}
}
return YES;
}
This works very well except for the bloody "Frame Load Interrupted" error. I had thought that by returning false from webView:shouldStartLoadWithRequest:navigationType:
that the web view would not load the request and therefore there would be no errors to handle. But even though I return NO
above, I still "Frame Load Interrupted" error. Why is that?
除了该死的“帧加载被中断”错误之外,这一方法非常有效。我认为通过从webView返回false:shouldStartLoadWithRequest:navigationType: web视图不会加载请求,因此不会有错误需要处理。但是即使我返回NO上面,我仍然“帧加载中断”错误。这是为什么呢?
Anyway, I'm assuming it can be ignored in -webView:didFailLoadWithError:
:
无论如何,我假设它可以在-webView中被忽略:didFailLoadWithError:
- (void)webView:(UIWebView *)wv didFailLoadWithError:(NSError *)error {
// Ignore NSURLErrorDomain error -999.
if (error.code == NSURLErrorCancelled) return;
// Ignore "Fame Load Interrupted" errors. Seen after app store links.
if (error.code == 102 && [error.domain isEqual:@"WebKitErrorDomain"]) return;
// Normal error handling…
}
And now iTunes URLs work properly, as do mailto:
s and app links.
现在iTunes url可以正常工作了,mailto:s和app链接也是如此。
#2
8
Starting with Theory's code, examine the URL for "itms" scheme(s) (this method can be called multiple times due to redirects). Once you see an "itms" scheme, stop the webView from loading and open the URL with Safari. My WebView happens to be in a NavigationController, so I pop out of that after opening Safari (less flashing).
从Theory的代码开始,检查“itms”方案的URL(由于重定向,可以多次调用此方法)。一旦您看到“itms”方案,请停止webView的加载并使用Safari打开URL。我的WebView碰巧是在一个NavigationController中,所以我在打开Safari(少闪烁)之后就跳出来了。
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request
navigationType:(UIWebViewNavigationType)navigationType
{
if ([[[request URL] scheme] isEqualToString:@"itms-apps"]) {
[webView stopLoading];
[[UIApplication sharedApplication] openURL:[request URL]];
[self.navigationController popViewControllerAnimated:YES];
return NO;
} else {
return YES;
}
}
#3
-2
Does it help if you register your app for handling itms: links?
如果你注册你的应用来处理itms:链接,会有帮助吗?
e.g. http://inchoo.net/iphone-development/launching-application-via-url-scheme/
例如,http://inchoo.net/iphone-development/launching-application-via-url-scheme/
You may start with scheme http
but then get an itms
redirect, which could fail if your app is not registered as handling that scheme.
您可以从scheme http开始,然后获得itms重定向,如果您的应用程序没有注册为处理该方案,那么它可能会失败。