2

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

在我的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 仍然可见。我在我的 web 应用程序中从一个页面导航到另一个页面,并且所有 javascript 在其中都运行良好,但是不再调用 webview 的“shouldStartLoadWithRequest”委托方法。我不知道为什么。有没有人有任何想法?

4

4 回答 4

0

检查了科尔多瓦,他们有自己的排队系统,并没有真正的帮助。但...

不听话的媒体的回答给了我一个想法。为什么不试试 window.location.hash,而不是 window.location。

现在一些用于记录的 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,因此我选择了波浪号而不是冒号,并增加了索引。现在您可以随意记录所有命令并发送您想要的任意数量的命令,它们都会通过:-)

于 2013-11-22T01:31:22.743 回答
0

我注意到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 委托有关的问题。

于 2013-07-14T22:52:13.173 回答
0

我(令人尴尬地)今天花了几个小时来处理这个问题,并意识到在我的 viewDidDisappear 中:我将 UIWebViewDelegate 设置为 nil!

我需要做的就是修复模态框后,重新设置 UIWebViewDelegate 并且一切都恢复正常。

于 2014-09-19T06:13:13.123 回答
0

我刚刚遇到了同样的问题,但与使用 href="#" 锚点有关。

这个 Stack Overflow 的答案对它进行了排序

该线程上有更多与widow.location有关的答案,因此您可能会很幸运。

于 2013-08-07T10:10:29.683 回答