UIWebView shouldStartLoadWithRequest仅在从内部调用模态视图时触发一次

我的部分应用程序用JS编写并在WebView中运行。 我正在使用UIWebView的shouldStartLoadWithRequest方法捕获http请求,作为JS和obj-c之间通信的一种方式。 这很有用,直到我尝试从shouldStartLoadWithRequest方法内部加载我的webview上的模态视图控制器。 一旦发生这种情况,就不再调用shouldStartLoadWithRequest。 有时我需要关闭这个模态视图控制器并返回到webview并做一些事情,然后重新呈现模态控制器。 模态控制器第一次出现就好了,然后我解雇它并尝试通过导航到javascript的URL再次呈现它,它不再出现。 永远不会运行shouldStartLoadWithRequest中的NSLog。

在我的JavaScript中我做这样的事情:

window.location='myapp:whateverMethod'; 

目标c代码如下所示:

 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *requestString = [[request URL] absoluteString]; NSLog(@"REQUEST URL: %@", requestString); if([requestString hasPrefix:@"myapp:"]) { NSArray *components = [requestString componentsSeparatedByString:@":"]; NSString *function = [components objectAtIndex:1]; if([self respondsToSelector:NSSelectorFromString(function)]) { [self performSelector:NSSelectorFromString(function)]; } return NO; } return YES; } -(void) whateverMethod { NSLog(@"whateverMethod called!"); // This is a quick way to grab my view controller from the storyboard, so assume it exists UIViewController *splash = [self.storyboard instantiateViewControllerWithIdentifier:@"splashViewController"]; [self presentModalViewController:splash animated:NO]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{ [self dismissModalViewController:splash animated:NO]; }); } 

此时我的webview仍然可见。 我在我的webapp中从一个页面导航到另一个页面,并且所有javascript都很好用,但不再调用webview的“shouldStartLoadWithRequest”委托方法。 我无法弄清楚为什么。 有没有人有任何想法?

我注意到Cordova没有设置window.location属性。 相反,它有两个选项:它创建一个iframe并将iframe的src设置为该url,或者它创建一个XMLHttpRequest对象,例如在iOSExec()函数中:

  if (bridgeMode) { execXhr = execXhr || new XMLHttpRequest(); // Changeing this to a GET will make the XHR reach the URIProtocol on 4.2. // For some reason it still doesn't work though... execXhr.open('HEAD', "file:///!gap_exec", true); execXhr.setRequestHeader('vc', cordova.iOSVCAddr); if (shouldBundleCommandJson()) { execXhr.setRequestHeader('cmds', nativecomm()); } execXhr.send(null); } else { execIframe = execIframe || createExecIframe(); execIframe.src = "gap://ready"; } 

话虽这么说,使用像Cordova这样的东西而不是试图自己滚动(即使它只是嵌入他们的视图控制器)可能是有益的,因为它们处理了webview代表提出的许多令人头疼的问题。

我刚遇到同样的问题,但与使用href =“#”锚相关。

此Stack Overflow答案对其进行了排序

该线程有更多的答案可以处理widow.location,所以你可能会对它们有好运。

检查出Cordova并且他们有自己的排队系统,而不是真正的帮助。 但…

Disobedient Media的回答给了我一个想法。 而不是window.location,为什么不尝试window.location.hash。

现在一些用于记录的JS代码是:

 function sendMsgToNative(msg) { window.location.hash = '~cmd~' + msg; } console.log = function (msg) { sendMsgToNative('log~js ' + msg); }; 

而Objective-C代码是:

 NSString *req = [request.URL absoluteString]; NSArray *components = [req componentsSeparatedByString:@"~"]; // Check for your protocol if ([components count] > 1 && [(NSString *)[components objectAtIndex:1] isEqualToString:@"cmd"]) { // Look for specific actions if ([(NSString *)[components objectAtIndex:2] isEqualToString:@"log"]) { NSString *logStr = [(NSString *)[components objectAtIndex:3] stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; LOGI("%@", logStr); } } 

您将获得包含“http:…”的完整URL,因此我选择了代字号而不是冒号,并增加了索引。 现在你可以记录所有的willy-nilly并发送你想要的任何数量的命令,他们都将通过:-)

我(尴尬地)今天花了几个小时研究这个,并意识到在我的viewDidDisappear中:我将UIWebViewDelegate设置为nil!

我需要做的就是修复一旦模态被解除,重新设置UIWebViewDelegate,一切都恢复正常。