In iOS, come posso chiamare un metodo Objective-C da Javascript in un UIWebView
e inviarlo di nuovo ai Javascript? So che questo potrebbe essere fatto su OS X usando la libreria Webkit, ma è ansible su iOS? Come fa PhoneGap a raggiungere questo objective?
C’è un’API per chiamare JavaScript direttamente da Objective-C, ma non puoi chiamare Objective-C direttamente da Javascript.
È necessario serializzare l’azione Javascript in un URL speciale e intercettare shouldStartLoadWithRequest
metodo shouldStartLoadWithRequest del delegato di shouldStartLoadWithRequest
.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;
Lì puoi deserializzare quell’URL speciale e interpretarlo per fare ciò che vuoi sul lato Objective-C. (Si dovrebbe restituire NO
nel metodo shouldStartLoadWithRequest
precedente in modo che UIWebView non utilizzi l’URL fasullo per effettuare effettivamente una richiesta HTTP per caricare una pagina Web.)
Quindi puoi eseguire Javascript da Objective-C chiamando questo metodo sulla tua webview.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
Raccomando di utilizzare uno schema URL fasullo, quindi sarà facile capire la differenza tra gli URL delle azioni e le richieste legittime. Puoi fare questa richiesta nel Javascript seguendo queste linee:
// JavaScript to send an action to your Objective-C code var myAppName = 'myfakeappname'; var myActionType = 'myJavascriptActionType'; var myActionParameters = {}; // put extra info into a dict if you need it // (separating the actionType from parameters makes it easier to parse in ObjC.) var jsonString = (JSON.stringify(myActionParameters)); var escapedJsonParameters = escape(jsonString); var url = myAppName + '://' + myActionType + "#" + escapedJsonParameters; document.location.href = url;
Quindi, nel metodo shouldStartLoadWithRequest
, è ansible esaminare lo schema e il frammento dell’URL per verificare se si tratta di una richiesta normale o di una delle azioni speciali. (Il frammento di un URL è ciò che viene dopo il #
).
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { // these need to match the values defined in your JavaScript NSString *myAppScheme = @"myfakeappname"; NSString *myActionType = @"myJavascriptActionType"; // ignore legit webview requests so they load normally if (![request.URL.scheme isEqualToString:myAppScheme]) { return YES; } // get the action from the path NSString *actionType = request.URL.host; // deserialize the request JSON NSString *jsonDictString = [request.URL.fragment stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; // look at the actionType and do whatever you want here if ([actionType isEqualToString:myActionType]) { // do something in response to your javascript action // if you used an action parameters dict, deserialize and inspect it here } // make sure to return NO so that your webview doesn't try to load your made-up URL return NO; }
(Leggi questa risposta se hai bisogno di aiuto per deserializzare la tua stringa json in un NSDictionary.)
La modifica della posizione della pagina può causare diversi problemi :
La soluzione, come offerta qui , è:
Continua a utilizzare la stessa tecnica URL (su js e ogg-c), cambia la posizione con un iframe:
var iframe = document.createElement("IFRAME"); iframe.setAttribute("src", "js-frame:myObjectiveCFunction"; document.documentElement.appendChild(iframe); iframe.parentNode.removeChild(iframe); iframe = null;
Spero possa aiutare
Da Objective-C: puoi passare una funzione javascript in una stringa a UIWebView. La pagina web la eseguirà e restituirà un risultato. In questo modo puoi passare variabili e ottenere dati da Javascript.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
Esempio:
NSString *script = @"document.getElementById('myTextField').value"; NSString *output = [myWebView stringByEvaluatingJavaScriptFromString:script];
Da Javascript: passa i tuoi dati all’interno dell’URL. Intercetta richieste URL in UIWebViewDelegate. Ottieni i dati e interrompi la richiesta dell’URL restituendo NO.
Intercettare la richiesta URL
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType