Come invocare il metodo Objective C da Javascript e inviare i dati a Javascript in iOS?

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.

Come dire al tuo codice Objective-C di fare qualcosa da Javascript nella tua WebView

È 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.)

Come eseguire il codice Javascript da Objective-C

Quindi puoi eseguire Javascript da Objective-C chiamando questo metodo sulla tua webview.

 - (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script; 

Codice di esempio

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 :

  1. Tutti setInterval e setTimeout si fermano immediatamente sul cambio di posizione
  2. Ogni innerHTML non funzionerà dopo un cambio di posizione annullato!
  3. Potresti ricevere altri bug davvero strani, davvero difficili da diagnosticare …

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