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

时间:2013-07-13 07:01:06

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

我的部分应用程序是用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];
    });
}

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

4 个答案:

答案 0 :(得分: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代表。

答案 1 :(得分:0)

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

This Stack Overflow answer sorted it

该线程上有更多关于widow.location的答案,所以你可以幸运。

答案 2 :(得分:0)

检查出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:...'所以我选择了代字号而不是冒号,并增加了索引。 现在你可以记录所有不受欢迎的命令并发送你想要的任何数量的命令,它们都将通过: - )

答案 3 :(得分:0)

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

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