Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle app URLs in a UIWebView?

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."

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:

- (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:

  1. 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?
  2. 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.

How do you handle such requests?

like image 946
theory Avatar asked Nov 28 '10 22:11

theory


People also ask

Is UIWebView deprecated?

Apple is phasing out UIWebView, which is used by developers for integrating web content into an app in a quick and secure manner. Apple is replacing UIWebView (and WebView) with WKWebView, an updated version, as UIWebView has been deprecated.

Which browser is used in iOS Webview?

Which browser iOS use in their webview? Safari browser installed in iOS & webview browser (if safari) are same or there are difference?

What is the difference between UIWebView and WKWebView?

Difference Between UIWebview and WKWebViewUIWebview is a part of UIKit, so it is available to your apps as standard. You don't need to import anything, it will we there by default. But WKWebView is run in a separate process to your app,. You need to import Webkit to use WKWebView in your app.

When was UIWebView deprecated?

And last year, we announced that the App Store will no longer accept app updates containing UIWebView as of December 2020.


2 Answers

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:

- (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?

Anyway, I'm assuming it can be ignored in -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.

like image 121
theory Avatar answered Oct 07 '22 01:10

theory


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).

- (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;     } } 
like image 31
Steve Spencer Avatar answered Oct 07 '22 01:10

Steve Spencer