Iphone 当从内部调用模式视图时,UIWebView应仅激发一次StartLoadWithRequest
我的应用程序有一部分是用JS编写的,在WebView中运行。我使用UIWebView shouldStartLoadWithRequest方法捕获http请求,作为JS和obj-c之间通信的一种方式。在我尝试从shouldStartLoadWithRequest方法内部在webview上加载一个模态视图控制器之前,这是非常有效的。一旦发生这种情况,就不再调用shouldStartLoadWithRequest。有时,我需要关闭这个模态视图控制器,返回webview并执行一些操作,然后重新显示模态控制器。模态控制器第一次出现时很好,然后我将其关闭,并尝试通过从javascript导航到URL来再次显示它,它将不再显示自己。shouldStartLoadWithRequest中的NSLogs永远不会运行 在我的javascript中,我执行以下操作:Iphone 当从内部调用模式视图时,UIWebView应仅激发一次StartLoadWithRequest,iphone,ios,objective-c,ipad,iphone-web-app,Iphone,Ios,Objective C,Ipad,Iphone Web App,我的应用程序有一部分是用JS编写的,在WebView中运行。我使用UIWebView shouldStartLoadWithRequest方法捕获http请求,作为JS和obj-c之间通信的一种方式。在我尝试从shouldStartLoadWithRequest方法内部在webview上加载一个模态视图控制器之前,这是非常有效的。一旦发生这种情况,就不再调用shouldStartLoadWithRequest。有时,我需要关闭这个模态视图控制器,返回webview并执行一些操作,然后重新显示模态
window.location='myapp:whateverMethod';
- (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];
});
}
目标c代码如下所示:
window.location='myapp:whateverMethod';
- (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的“shouldstartoadwithrequest”委托方法不再被调用。我不明白为什么。有人有什么想法吗?我注意到没有设置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";
}
也就是说,使用类似的东西而不是自己尝试滚动它(即使只是嵌入他们的视图控制器)可能是有益的,因为它们处理了webview代理带来的许多头痛问题。我也遇到了同样的问题,但与使用href=“#”锚相关
关于widow.location,该线程中有更多的答案,因此您可能会很幸运。查看了Cordova,他们有自己的排队系统,而不是真正的帮助。但是 不听话的媒体的回答给了我一个想法。为什么不试试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);
}
}
您得到了完整的URL,包括“http:…”,因此我选择了tilde而不是冒号,并增加了索引。
现在,您可以随意登录所有日志,并发送任意数量的命令,这些命令都将通过:-)我(尴尬地)今天花了几个小时来完成这项工作,并意识到在我的视图中消失了:我将UIWebViewDelegate设置为零
我所需要做的只是在模式被取消后,重新设置UIWebViewDelegate,然后一切都恢复正常 有趣。实际上,我已经尝试过使用这两种方法创建请求,并且得到了完全相同的结果(shouldstarting将执行,直到出现一个模式窗口,然后停止)。用科尔多瓦试一试,看看是否会有同样的结果。这感觉像是iOS中的细微差别,但我可能错了。在没有找到一个适合本项目需要的解决方案后,我最终使用CSS动画等模仿了webview内部的模式视图(与模式视图的外观非常接近),因此不再需要隐藏webview。