Sous iOS, comment puis-je appeler une méthode Objective-C à partir de Javascript dans un UIWebView
et lui faire renvoyer des données vers Javascript? Je sais que cela pourrait être fait sur OS X en utilisant la bibliothèque Webkit, mais est-ce possible sur iOS? Comment PhoneGap y parvient-il?
Il existe une API pour appeler JavaScript directement depuis Objective-C, mais vous ne pouvez pas appeler Objective-C directement depuis Javascript.
Vous devez sérialiser votre action Javascript en une URL spéciale et intercepter cette URL dans la méthode shouldStartLoadWithRequest
du délégué UIWebView.
- (BOOL)webView:(UIWebView *)webView
shouldStartLoadWithRequest:(NSURLRequest *)request
navigationType:(UIWebViewNavigationType)navigationType;
Là, vous pouvez désérialiser cette URL spéciale et l'interpréter pour faire ce que vous voulez du côté Objective-C. (Vous devez retourner NO
dans la méthode shouldStartLoadWithRequest
ci-dessus pour que UIWebView n'utilise pas votre URL bidon pour réellement faire une requête HTTP pour charger une page Web.)
Ensuite, vous pouvez exécuter Javascript à partir d'Objective-C en appelant cette méthode sur votre vue Web.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
Je recommande d'utiliser un schéma d'URL bidon afin qu'il soit facile de faire la différence entre vos URL d'action et vos demandes légitimes. Vous pouvez faire cette demande dans le Javascript en suivant ces lignes:
// 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;
Ensuite, dans la méthode shouldStartLoadWithRequest
de UIWebView.delegate
, Vous pouvez inspecter le schéma d'URL et le fragment pour vérifier s'il s'agit d'une demande normale ou de l'une de vos actions spéciales. (Le fragment d'une URL est ce qui vient après le #
.)
- (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;
}
(Lisez cette réponse si vous avez besoin d'aide pour désérialiser votre chaîne json en NSDictionary.)
La modification de l'emplacement de la page peut entraîner plusieurs problèmes :
La solution proposée ici , est:
Continuez à utiliser la même technique d'URL (sur js et objective-c), changez simplement l'emplacement avec un iframe:
var iframe = document.createElement("IFRAME");
iframe.setAttribute("src", "js-frame:myObjectiveCFunction";
document.documentElement.appendChild(iframe);
iframe.parentNode.removeChild(iframe);
iframe = null;
J'espère que cela pourra aider
Depuis Objective-C: vous pouvez transmettre une fonction javascript dans une chaîne à UIWebView. La page Web l'exécutera et retournera un résultat. De cette façon, vous pouvez transmettre des variables et récupérer des données à partir de Javascript.
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
Exemple:
NSString *script = @"document.getElementById('myTextField').value";
NSString *output = [myWebView stringByEvaluatingJavaScriptFromString:script];
Depuis Javascript: passez vos données dans l'URL. Intercepter les demandes d'URL dans UIWebViewDelegate. Obtenez les données et annulez la demande d'URL en renvoyant NON.
<script>window.location = "url://key1/value1"; </script>
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType