我已經實現了什麼似乎是使用UIWebView委託shouldStartLoadWithRequest()方法從iOS通信到iOS上的objective-c的唯一方式。iOS從Javascript調用Objective-C:有些調用被忽略?
它似乎一開始工作正常,但現在我注意到,如果我在短時間內從javascript到objective-c多次調用,通常會忽略第二個調用(應用程序是一個鋼琴鍵盤,每個按鍵觸發對本地代碼的調用,當處理多次觸摸時,本地代碼不會被每個手指調用)。
這是我的客觀c代碼來響應JavaScript調用。我知道這很詭異,但我只想要一些現在可行的東西。
- (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,所以如果他們沒有這個問題,那麼我很想弄清楚他們正在做什麼來完成這項工作。
更新:
我剛剛發現這一點:send a notification from javascript in UIWebView to ObjectiveC 這證實了我對臨門迷路的通話懷疑。顯然,我需要將我的電話合併到一起,或者手動延遲電話,以便在再次撥打電話時返回url請求。
問題是第一個window.src集合必須已經完成,然後才能發送另一個,最終因爲runloop是單線程和同步的。除了排隊和/或批處理呼叫之外,沒有辦法解決,直到第一個完成。實現這個完美實際上是相當棘手的,特別是在發送第一個onClick on Mobile Safari之前考慮到延遲的情況下,所以最好的辦法是將源代碼查看到其中一個開源橋接器 - 或者更好的是,只需使用一。 – abarnert