【问题标题】:UIWebView shouldStartLoadWithRequest only fires once when calling a modal view from insideUIWebView shouldStartLoadWithRequest 仅在从内部调用模态视图时触发一次
【发布时间】:2013-07-11 18:13:02
【问题描述】:

我的应用程序的一部分是用 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”委托方法。我不知道为什么。有人有什么想法吗?

【问题讨论】:

  • 在没有找到适合该项目需求的解决方案后,我最终使用 CSS 动画等模仿了 webview 内部的模态视图(足够接近模态视图的样子),因此没有不得不隐藏 webview 了。

标签: iphone ios objective-c ipad iphone-web-app


【解决方案1】:

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

【讨论】:

  • 有趣。实际上,我已经尝试使用这两种方法创建请求并体验到完全相同的结果(应该执行 StartLoading 直到出现模式窗口,然后停止)。用cordova试试看是否会发生同样的结果会很有趣。这感觉像是 iOS 中的细微差别,但我可能是错的。
【解决方案2】:

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

This Stack Overflow answer sorted it

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

【讨论】:

    【解决方案3】:

    检查了 Cordova,他们有自己的排队系统,并没有真正的帮助。但是……

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

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-03-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-21
        • 2013-09-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多