Appel d'une fonction Objective-C via JavaScript (UIWebView)

Bonjour à  tous,

 

Voilà  plusieurs jours que j'essaie ceci, sans succès  >:(

 

Je suis en train de créer une petite application iPhone basée sur un composant UIWebView et je voudrais pouvoir appeler certaines fonctions natives Objective-C via JavaScript et y faire passer des paramètres.

 

Un exemple très simple.

 

En JavaScript je voudrais executer cette fonction : alert(monApp.maFonction(1000, 5));


 


En Objective-C je voudrais :

  1. pouvoir détecter l'appel de cette fonction,

  2. pouvoir récupérer les paramètres ("1000" et "5" dans l'exemple ci-dessus),

  3. travailler avec (ex : 1000 x 5),

  4. récupérer du côté JavaScript la valeur de retour (donc "5000", qui sera affiché dans le alert).

 

Dans cet exemple je fais une simple multiplication des deux paramètres, mais mon objectif est de pouvoir écrire dans un fichier ou bien enregistrer une image dans l'album photo et obtenir une valeur booléenne en retour ; ou bien executer une procédure GET et d'obtenir du texte en retour (...).

 

Est-ce que quelqu'un aurait une piste à  me donner ?

Est-ce possible via stringByEvaluatingJavaScriptFromString ?

 


Merci par avance pour votre aide :)


 


Beny


Réponses



  •  


    En JavaScript je voudrais executer cette fonction : alert(monApp.maFonction(1000, 5));


     



     


    C'est impossible, l'Objective-C est un langage compilé il n'y a donc pas de possibilité d'appeler une fonction Objective-C depuis Javascript. Si c'est bien ce que tu veux faire j'avoue que tout n'est pas super clair pour moi !


     





    En Objective-C je voudrais :


      1. pouvoir détecter l'appel de cette fonction,

      2. pouvoir récupérer les paramètres ("1000" et "5" dans l'exemple ci-dessus),

      3. travailler avec (ex : 1000 x 5),

      4. récupérer du côté JavaScript la valeur de retour (donc "5000", qui sera affiché dans le alert).

     




     


    Je n'ai pas tout saisi. Peut être peux tu m'en dire plus sur ce que tu veux faire concrètement. Tu veux depuis un app iOS appeler une fonction JS et en récupérer le résultat c'est bien ça ? Et depuis ta fonction javascript appeler une méthode Objective-C et en récupérer le résultat ?


     


    Je serais intéressé de savoir pourquoi tu souhaites absolument passer par JS. Bien souvent quand il est question de communiquer avec un composant web il est préférable de passer par une API.


     


    Il y a sur ce forum des gens bien plus expérimentés que moi peut être qu'il comprendrons mieux que moi !

  • Hello,


     


    Regarde du coté JavaScriptCore. Voici un lien qui t'aidera :


     


    http://nshipster.com/javascriptcore/


  • AliGatorAliGator Membre, Modérateur
    @revlam C'est tout à  fait possible, c'est d'ailleurs l'idée a la base de tous les frameworks type PhoneGap & co.


    Je plussoie le lien de Samir, c'est avec JavaScriptCore que, du côté Objective-C, tu vas déclarer des APIs ObjC à  exposer à  ton moteur JavaScript. Ensuite côté JS il suffira d'appeler ces points d'entrée que tu as exposés comme si c'était des fonctions JS normales et JavaScriptCore va se charger de convertir tout seul les types des arguments JS en types ObjC (String -> NSString etc) et vice-versa pour la valeur de retour, de sorte que ça devient transparent côté JS.


  • @revlam C'est tout à  fait possible, c'est d'ailleurs l'idée a la base de tous les frameworks type PhoneGap & co.

     




     


    Ah je ne savais pas mais du coup ce n'est pas un appel de fonction directement de JS vers l'app ? Sinon je ne comprend plus rien à  la compilation... Bon ce n'est pas l'objet du sujet mais je serais curieux de savoir comment ça marche concrètement !! 

  • AliGatorAliGator Membre, Modérateur
    JavaScriptCore expose juste un point d'entrée vers un trampoline qui va wrapper les arguments et rediriger / jumper vers l'adresse memoire du code compilé.

    Ce n'est pas bien différent de quand tu fais appel à  une fonction d'une librairie compilée. Le fait que ce soit appelé depuis un code interprété n'est pas un problème puisque c'est JavaScriptCore qui se charge de l'interprétation du code JS et que c'est lui qui va injecter les points d'entrée.
  • Merci à  tous pour vos suggestions.


     


    Je ne connaissais pas JavaScriptCore et en effet ça facilite la vie !


    Grâce à  ça j'ai pu réussir à  faire ce que je veux 


     


    Je me suis basé sur cet exemple : https://github.com/TomSwift/UIWebView-TS_JavaScriptContext/


     


    Pour ceux que cela intéresse, vous trouverez ci-joint un ZIP avec un projet XCode d'exemple.


     


    J'ai fait exactement comment mentionné dans mon premier post, c'est à  dire lancer une fonction JavaScript avec deux paramètres (via un UIWebView) et, en Objective-C, multiplier ces deux valeurs l'une par l'autre. Ensuite je récupère le total que j'affiche dans un alert.


     


    En gros, dans mon fichier HTML il y a cela :



    <button type="button" onclick="alert(sayHello(1000, 5));">Cliquez-moi</button>

    Et dans mon fichier ViewController.m il y a cela :




    - (void)webView:(UIWebView *)webView didCreateJavaScriptContext:(JSContext *)context {
        context[@sayHello] = ^(JSValue *value, JSValue *multi) {
            int x = [value toInt32] * [multi toInt32];
            NSString *output = [NSString stringWithFormat:@TOTAL : %d, x];
            NSLog(@%@", output);
            return output;
        };
    }


     

    En espérant que cela puisse aider ceux qui cherchent à  faire pareil :)



  • JavaScriptCore expose juste un point d'entrée vers un trampoline qui va wrapper les arguments et rediriger / jumper vers l'adresse memoire du code compilé.

    Ce n'est pas bien différent de quand tu fais appel à  une fonction d'une librairie compilée. Le fait que ce soit appelé depuis un code interprété n'est pas un problème puisque c'est JavaScriptCore qui se charge de l'interprétation du code JS et que c'est lui qui va injecter les points d'entrée.




     


    Je ne connaissais pas JavaScriptCore mais du coup la présence de ce framework explique tout. Merci même si j'ai encore du mal à  en voir l'utilité pour le moment.


     


    @rhododendron sans indiscrétions peux-tu m'expliquer dans quelle situation tu as ce besoin ?

  • rhododendronrhododendron Membre
    avril 2015 modifié #10

    J'ai besoin de cela car ça me permet de concevoir une application complète en HTML5/CSS3/jQuery et ensuite de la distribuer sur iOS et Android sans avoir à  retoucher au code.


     


    Je modifie juste les API-maisons que j'appellerai en JavaScript :)


     


    Concrètement je vais avoir besoin d'enregistrer une image dans l'album photo, de faire une requête GET pour obtenir le code-source d'une page distante, d'écrire dans un fichier pour enregistrer les paramètres utilisateur de l'app, etc.


     


    PhoneGap/Cordova pourraient faire l'affaire, mais je préfère garder la main sur l'ensemble.


  • Joanna CarterJoanna Carter Membre, Modérateur
    avril 2015 modifié #11
    Il me semble que tu essaies à  réinventer la roue. Ce sera un sacré boulot de fournir tout ce qu'il faut.
  • * soupire * Et l'ergonomie sera la même sur les deux OS ?


  • rhododendronrhododendron Membre
    avril 2015 modifié #13

    Je n'ai pas besoin de tout avoir de dispo en JavaScript, mais juste quelques fonctions utiles me permettant de faire des choses impossible en JavaScript.


     


    Enregistrer une image dans la Pellicule, c'est impossible en JavaScript.


    Executer un GET pour obtenir le code-source d'une page, ce n'est pas possible non plus (sauf via Ajax + Same Origin Policy).


     


    Concernant l'ergonomie, certains éléments changent bien sur, j'adapte le CSS à  l'environnement.


    Mais ça c'est une autre histoire :)


     


    Le HTML5/CSS3/jQuery, c'est l'avenir.


     


    EDIT :


     


    Je vous donne un exemple plus concret d'utilisation.


    Sur Mac il y a une petite application qui s'appelle Sentenza Desktop et qui permet de concevoir des apps Mac OS X avec du contenu HTML5/CSS3/JS et une petite bibliothèque d'API.


     


    Il y a des jeux développés en HTML5/CSS3 qui sont très bien conçu.


    Les déployer sur plusieurs plateformes devient facile avec des solutions comme ça (comme PhoneGap).


    On développe 99% du code une fois, et on modifie 1% selon chaque plateforme.


     


    Dans le cas d'un jeu HTML5 il faudra utiliser une fonction native pour enregistrer les scores dans un fichier texte.


     



  • Je ne suis pas très convaincu à  première vue, mais je regarderais ton outil.

  • Si tu sais développer en Objective-C, cet outil n'est d'aucun intérêt pour toi.


    C'est plutôt pour les web développeurs qui voudraient distribuer simplement un jeu HTML5.


     


    Et pour ceux qui doutent des performances d'une application mobile faite en HTML5/CSS3/JS, je vous laisse juger de ce qui était possible il y a déjà  deux ans :


     



  • DrakenDraken Membre
    avril 2015 modifié #16

    L'objective-C est bien trop geek pour moi. Alors que dire de l'HTML/CSS et JS .. Je suis juste bon pour swifter. Ceci dis, je suis plutôt gamedesigner que programmeur, alors c'est un peu normal.


  • MalaMala Membre, Modérateur


    Le HTML5/CSS3/jQuery, c'est l'avenir.




    C'est pas ce que disait Palm avec son Web OS à  une époque...  ::)

  • DrakenDraken Membre
    avril 2015 modifié #18

    M'enfin Mala, faut arrêter avec ce pessimisme. La plupart des experts sont unanimes. D'ici 2011, les solutions HTML5 et associées auront remplacés la plupart des anciens outils de développement...


  • Ahah, je suis de votre avis.


    Mais je pense honnêtement que dans les années à  venir l'HTML5/CSS3/JS (et surtout JS) vont prendre une part encore plus importante.


     


    Le développement natif ne sera jamais remplacé (nos DAB ne tourneront pas tout de suite sous Chrome OS ^_^ ).


    Mais je vois ça un peu comme les livres version numérique et version papier.




  • Le développement natif ne sera jamais remplacé (nos DAB ne tourneront pas tout de suite sous Chrome OS ^_^ ).




    Et c'est bien dommage pour Google, qui serait content d'avoir encore plus d'infos sur les flux financiers des gens.

  • MalaMala Membre, Modérateur


    Mais je pense honnêtement que dans les années à  venir l'HTML5/CSS3/JS (et surtout JS) vont prendre une part encore plus importante.




    C'est ce qu'on nous disait déjà  il y a dix ans. D'ailleurs fut un temps où Steve nous ventait le mérite des web apps pour faire du dev sous iOS. Puis, le système a été hacké. Des devs ont commencé à  montrer le potentiel des applications natives et le Jobs a retourné sa veste pour nous sortir l'App Store.

  • AliGatorAliGator Membre, Modérateur
    C'est aussi ce que disait FaceBook il y a plusieurs années... avant finalement d'abandonner les WebApps pour refaire du natif.
    Et va aussi dire ça aux applications bancaires, qui nécessitent de la sécurité (Keychain, TouchID, mais aussi et surtout chiffrement de données, contrôle et limitation du cache pour éviter les fuites de données sensibles dans le cache web, et j'en passe).
Connectez-vous ou Inscrivez-vous pour répondre.