本文介绍了UIWebView加载因自定义URL方案而失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UIWebView,该UIWebView在我的应用程序中处理OAuth身份验证流. OAuth服务使用的回调URL指向我在应用程序中设置的自定义URL方案,我们将其称为mycustomurlscheme.

I have a UIWebView that is handling an OAuth authentication flow in my app. The callback URL that the OAuth service uses points to a custom URL scheme I've set up in my app, let's call it mycustomurlscheme.

因此,一旦用户成功进行身份验证,OAuth服务会将其重定向到URL mycustomurlscheme://oauth/success?oauth_token = xxxxxxxxxxxxxxxxxxxx& oauth_verifier = xxxxxxxxxxxxxxxxxxxx .当UIWebView请求此URL时,该应用程序的行为正确;即,调用了我的应用程序委托中的application:openURL:sourceApplication:annotation:方法,我关闭了UIWebView并继续使用该应用程序.

So once the user authenticates successfully, the OAuth service redirects them to the URL mycustomurlscheme://oauth/success?oauth_token=xxxxxxxxxxxxxxxxxxxx&oauth_verifier=xxxxxxxxxxxxxxxxxxxx. When the UIWebView requests this URL, the app behaves correctly; namely, the application:openURL:sourceApplication:annotation: method in my app delegate gets called, and I dismiss the UIWebView and continue on with the app.

但是,我在UIWebView中记录了加载失败(使用webView:didFailLoadWithError:),并且当上述过程发生时,我在控制台中看到以下内容:

However, I am logging load failures in the UIWebView (using webView:didFailLoadWithError:), and when the above process happens, I see the following in the console:

Error Domain=WebKitErrorDomain Code=102 "Frame load interrupted" UserInfo=0xa1a4810 {NSErrorFailingURLKey=mycustomurlscheme://oauth/success?oauth_token= xxxxxxxxxxxxxxxxxxxx&oauth_verifier=xxxxxxxxxxxxxxxxxxxx, NSErrorFailingURLStringKey=mycustomurlscheme://oauth/success?oauth_token= xxxxxxxxxxxxxxxxxxxx&oauth_verifier=xxxxxxxxxxxxxxxxxxxx, NSLocalizedDescription=Frame load interrupted}

我尝试实现以下UIWebViewDelegate方法,以为拦截请求可以避免该错误,但是该错误仍然会发生:

I tried implementing the following UIWebViewDelegate method, thinking that intercepting the request would avoid the error, but the error still happens:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request
 navigationType:(UIWebViewNavigationType)navigationType
{
    if ([request.URL.scheme isEqualToString:@"mycustomurlscheme"]) {
        [[UIApplication sharedApplication] openURL:request.URL];
        return NO;
    } else {
        return YES;
    }
}

然后,此代码使我的应用程序委托中的以下代码运行:

This code then causes the following code in my app delegate to run:

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
    NSNotification *notification = [NSNotification notificationWithName:kDSApplicationLaunchedWithURLNotification object:nil userInfo:@{kApplicationLaunchOptionsURLKey: url}];
    [[NSNotificationCenter defaultCenter] postNotification:notification];

    return YES;
}

此通知将由以下继续加载&的程序段获取.启动应用程序,后授权:

This notification is picked up by the following block that continues the loading & launching of the app, post-authorization:

self.applicationLaunchNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kDSApplicationLaunchedWithURLNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) {
                    NSURL *url = [notification.userInfo valueForKey:kApplicationLaunchOptionsURLKey];
                    currentRequestToken.verifier = [DSAPIParametersFromQueryString([url query]) valueForKey:@"oauth_verifier"];

                    [[DSAPIManager sharedManager] acquireAccessTokenWithRequestToken:currentRequestToken success:^(DSAPIOAuth1Token * accessToken) {
                        [self finishLogin];
                    } failure:^(NSError *error) {
                        [self removeAsObserver];
                        [self showAlert:NSLocalizedString(@"Could not authorize the app. Please try again later.", nil)];
                    }];
                }];

finishLoginremoveAsObserver方法如下:

- (void)finishLogin
{
    [self removeAsObserver];
    [self.navigationController dismissViewControllerAnimated:YES completion:^{
        [self performSegueWithIdentifier:@"PostLoginSegue" sender:self];
    }];
}

- (void)removeAsObserver
{
    if (self.applicationLaunchNotificationObserver) {
        [[NSNotificationCenter defaultCenter] removeObserver:self.applicationLaunchNotificationObserver];
        self.applicationLaunchNotificationObserver = nil;
    }
}

忽略此错误消息是否安全?有人知道为什么会这样吗?我的直觉是,UIWebView认为URL的方案无效,但电话知道可以.如果是这样,有什么办法可以告诉UIWebView(或WebKit引擎)此方案有效吗?

Is it safe to ignore this error message? Anyone know why it's happening? My hunch is that the UIWebView thinks the URL has an invalid scheme, but the phone knows it's ok. If that's the case is there any way to tell the UIWebView (or the WebKit engine) that this scheme is valid?

推荐答案

此处的错误实际上是Frame load interrupted与url方案无关.完全有可能使用自定义网址方案,并且不会产生任何错误.我在许多应用程序中都安装了它们,但从未遇到过问题.

The error here is actually the Frame load interrupted nothing to do with the url scheme. Using custom url scheme is perfectly possible and doesn't create any errors. I have them in many of my apps and have never had a problem with them.

我相信您的问题是由于[webView stoploading];的原因,从技术上讲,它会在您return NO时停止加载,因此[webView stopLoading];只会导致该过程中断.删除此行,然后继续执行return NO,然后看看会发生什么,我99.9%确信这是原因.

I believe your issue is because of the [webView stoploading]; technically it will stop loading when you return NO so the [webView stopLoading]; is just causing an interruption in the process. Remove this line and let it continue to return NO and see what happens I am 99.9% sure this is the reason.

因此您的代码应类似于

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
    if ([request.URL.scheme isEqualToString:@"mycustomurlscheme"]) {
        // Dismiss the view controller, continue loading the app, etc.
        return NO;
    }

    return YES; // No need for the else statement if this is the only thing to happen if it fails the if statement.
}

更新

基于Don注释删除[webView stopLoading];不能解决您的问题.如果是这种情况,并且您将其放入if语句中,则我怀疑还有其他情况.您共享了所有代码吗?在您的代码中使用此// Dismiss the view controller, continue loading the app, etc.,我怀疑您没有共享所有内容,在这种情况下我们无济于事.

Based don comments removing [webView stopLoading]; didn't fix your issue. If this is the case and you make it into that if statement I suspect that something else is going on. Have you shared all your code? With this // Dismiss the view controller, continue loading the app, etc. in your code I suspect that you haven't shared everything in which case we can't help.

这篇关于UIWebView加载因自定义URL方案而失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 15:39