UIWebView デリゲート shouldStartLoadWithRequest() メソッドを使用して、iOS で JavaScript から Objective-C に通信する唯一の方法と思われるものを実装しました。
最初は問題なく動作しているように見えましたが、短期間に JavaScript から Objective-C を複数回呼び出すと、2 回目の呼び出しは通常無視されることに気付きました (アプリケーションはピアノの鍵盤で、キーを押すたびに呼び出しがトリガーされます)。複数のタッチを処理する場合、ネイティブコードはすべての指で呼び出されるわけではありません)。
これは、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 から、1 つの非表示の 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リクエストが返されるように、呼び出しをまとめるか、手動で呼び出しを遅らせる必要があるようです。