我已经使用 UIWebView 委托(delegate) shouldStartLoadWithRequest() 方法在 iOS 上实现了似乎是从 javascript 到 objective-c 通信的唯一方法。
起初似乎工作正常,但现在我注意到,如果我在短时间内多次从 javascript 调用 objective-c,第二次调用通常会被忽略(该应用程序是钢琴键盘,每次按键触发对 native 代码的调用,当处理多个触摸时, native 代码不会为每个手指都调用)。
这是我响应 javascript 调用的 objective-c 代码。我知道这很愚蠢,但我只是想要一些暂时可用的东西。
- (BOOL)webView:(UIWebView *)webView2 shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType
{
// Intercept custom location change, URL begins with "js-call:"
NSString * requestString = [[request URL] absoluteString];
if ([requestString hasPrefix:@"js-call:"])
{
// Extract the selector name from the URL
NSArray * components = [requestString componentsSeparatedByString:@":"];
NSString * functionCall = [components objectAtIndex:1];
NSArray * params = [functionCall componentsSeparatedByString:@"%20"];
NSString * functionName = [params objectAtIndex:0];
// Parse playnote event
if ([functionName isEqualToString:@"playNote"])
{
NSString * param = [params objectAtIndex:1];
NoteInstanceID note_id = [m_audioController playNote:[param intValue]];
NSString * jscall = [NSString stringWithFormat:@"document.PlayNoteCallback(%i);", note_id];
NSLog(@"playNote: %i", (int)note_id);
[m_webView stringByEvaluatingJavaScriptFromString:jscall];
}
// Parse stopnote event
if ([functionName isEqualToString:@"stopNote"])
{
NSString * param = [params objectAtIndex:1];
NoteInstanceID note_id = [param intValue];
NSLog(@"stopNote: %i", (int)note_id);
[m_audioController stopNote:note_id];
}
// Parse log event
if ([functionName isEqualToString:@"debugLog"])
{
NSString * str = [requestString stringByReplacingOccurrencesOfString:@"%20" withString:@" "];
NSLog(@"%s", [str cStringUsingEncoding:NSStringEncodingConversionAllowLossy]);
}
// Cancel the location change
return NO;
}
// Accept this location change
return YES;
}
在 javascript 中,我通过设置单个隐藏 iframe 的 src 属性来调用 objective-c 方法。这将触发 objective-c 中的委托(delegate)方法,然后将调用所需的 native 代码。
$("#app_handle").attr("src", "js-call:playNote " + key.data("pitch"));
app_handle 是相关 iframe 的 ID。
综上所述,我的方法基本可以,但是短时间内多次调用不行。这只是我们被迫从 javascript 到 objective-c 的可怕方法的产物吗?还是我做错了什么?我知道 PhoneGap 做了类似的事情来实现相同的目标。我宁愿不使用 PhoneGap,所以如果他们没有这个问题,那么我很想弄清楚他们正在做什么来使这项工作成功。
更新:
我刚找到这个:send a notification from javascript in UIWebView to ObjectiveC 这证实了我对快速连续调用的电话丢失的怀疑。显然,我需要将我的调用集中在一起或手动延迟调用,以便在我再次调用电话时返回 url 请求。
最佳答案
接受的答案没有解决问题,因为在第一个处理之前到达的位置更改仍然被忽略。查看第一条评论。
我建议采用以下方法:
function execute(url)
{
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", url);
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
}
您重复调用 execute
函数,由于每次调用都在其自己的 iframe 中执行,因此在快速调用时不应忽略它们。
归功于 this guy .
关于javascript - iOS 从 Javascript 调用 Objective-C : Some calls are ignored?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10609228/