简体   繁体   English

UIWebView加载失败,并带有自定义URL方案

[英]UIWebView load fails with custom URL scheme

I have a UIWebView that is handling an OAuth authentication flow in my app. 我有一个UIWebView,它在我的应用程序中处理OAuth身份验证流程。 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服务使用的回调网址指向我在我的应用中设置的自定义网址方案,我们称之为mycustomurlscheme

So once the user authenticates successfully, the OAuth service redirects them to the URL mycustomurlscheme://oauth/success?oauth_token=xxxxxxxxxxxxxxxxxxxx&oauth_verifier=xxxxxxxxxxxxxxxxxxxx . 因此,一旦用户成功进行身份验证,OAuth服务会将其重定向到URL mycustomurlscheme:// oauth / success?oauth_token = xxxxxxxxxxxxxxxxxxxx&oauth_verifier = xxxxxxxxxxxxxxxxxxxx When the UIWebView requests this URL, the app behaves correctly; 当UIWebView请求此URL时,该应用程序行为正常; namely, the application:openURL:sourceApplication:annotation: method in my app delegate gets called, and I dismiss the UIWebView and continue on with the app. application:openURL:sourceApplication:annotation:我的app委托中的方法被调用,我关闭UIWebView并继续使用该应用程序。

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: 但是,我在UIWebView中记录加载失败(使用webView:didFailLoadWithError: ,当上述过程发生时,我在控制台中看到以下内容:

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}

I tried implementing the following UIWebViewDelegate method, thinking that intercepting the request would avoid the error, but the error still happens: 我尝试实现以下UIWebViewDelegate方法,认为拦截请求将避免错误,但错误仍然发生:

- (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)];
                    }];
                }];

The finishLogin and removeAsObserver methods look like this: 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;
    }
}

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. 我的预感是UIWebView认为URL有一个无效的方案,但手机知道它没问题。 If that's the case is there any way to tell the UIWebView (or the WebKit engine) that this scheme is valid? 如果是这样的话有什么办法告诉UIWebView(或WebKit引擎)这个方案是有效的吗?

The error here is actually the Frame load interrupted nothing to do with the url scheme. 这里的错误实际上是Frame load interrupted与url方案无关。 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. 我在他的许多应用程序中都有它们,并且从未遇到过问题。

I believe your issue is because of the [webView stoploading]; 我相信你的问题是因为[webView stoploading]; technically it will stop loading when you return NO so the [webView stopLoading]; 从技术上讲,当你return NO时会停止加载,所以[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. 删除此行,让它继续return NO ,看看会发生什么,我99.9%肯定这是原因。

So your code would look like 所以你的代码看起来像

- (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.
}

UPDATE UPDATE

Based don comments removing [webView stopLoading]; 基于don评论删除[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. 如果是这种情况,你将其纳入if语句,我怀疑还有其他事情发生。 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. 使用此// Dismiss the view controller, continue loading the app, etc.在代码中// Dismiss the view controller, continue loading the app, etc.我怀疑你没有分享所有内容,在这种情况下我们无法提供帮助。

Check if there is anything for "UserAgent" in"standardUserDefaults". 检查“standardUserDefaults”中是否有“UserAgent”的内容。 There are chances that UserAgent is getting appended in request URL. UserAgent很可能会在请求URL中附加。 Or check for any "UserAgent" sent in url request. 或者检查在url请求中发送的任何“UserAgent”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM