我有一个 UIWebView 正在我的应用程序中处理 OAuth 身份验证流程。 OAuth 服务使用的回调 URL 指向我在应用程序中设置的自定义 URL 方案,我们称之为mycustomurlscheme
.
因此,一旦用户身份验证成功,OAuth 服务会将其重定向到 URLmycustomurlscheme://oauth/success?oauth_token=xxxxxxxxxxxxxxxxxxxx&oauth_verifier=xxxxxxxxxxxxxxxxxxxx。当 UIWebView 请求此 URL 时,应用程序会正常运行;即,application:openURL:sourceApplication:annotation:
我的应用程序委托中的方法被调用,我关闭 UIWebView 并继续使用该应用程序。
但是,我在 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}
我尝试实现以下 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;
}
}
然后,此代码会导致我的应用程序委托中的以下代码运行:
- (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;
}
此通知由以下块获取,该块在授权后继续加载和启动应用程序:
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
方法如下所示:
- (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 引擎)这个方案是有效的吗?