我已经使用 UIWebView 委托 shouldStartLoadWithRequest() 方法在 iOS 上实现了从 javascript 到 Objective-c 的唯一通信方式。
起初它似乎工作正常,但现在我注意到如果我在短时间内从javascript多次调用objective-c,第二次调用通常会被忽略(应用程序是钢琴键盘,每次按键都会触发一次调用对于本机代码,在处理多次触摸时,不会为每个手指调用本机代码)。
这是我响应 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 中的委托方法,然后将调用所需的本机代码。
$("#app_handle").attr("src", "js-call:playNote " + key.data("pitch"));
app_handle 是相关 iframe 的 id。
综上所述,我的方法基本可以,但是短时间内多次调用是不行的。这只是我们被迫从javascript到objective-c通信的可怕方法的产物吗?还是我做错了什么?我知道 PhoneGap 做了类似的事情来实现同样的目标。我宁愿不使用PhoneGap,所以如果他们没有这个问题,那么我很想弄清楚他们正在做什么来完成这项工作。
更新:
我刚刚发现:从 UIWebView 中的 javascript 向 ObjectiveC 发送通知, 这证实了我对快速连续调用丢失的怀疑。显然,我需要将我的呼叫集中在一起或手动延迟呼叫,以便在我拨打另一个呼叫时返回 url 请求。