web-dev-qa-db-fra.com

pont JavaScript iOS

Je travaille sur une application où je vais utiliser à la fois HTML5 dans UIWebView et le framework iOS natif. Je sais que je peux implémenter la communication entre JavaScript et Objective-C. Existe-t-il des bibliothèques qui simplifient la mise en œuvre de cette communication? Je sais qu'il existe plusieurs bibliothèques pour créer des applications iOS natives en HTML5 et en javascript (par exemple, AppMobi, PhoneGap), mais je ne suis pas sûr s'il existe une bibliothèque permettant de créer des applications iOS natives avec une utilisation intensive de JavaScript. J'ai besoin de:

  1. Exécuter des méthodes JS à partir d'Objective-C
  2. Exécuter les méthodes Objective-C à partir de JS
  3. Écoutez les événements JS natifs d'Objective-C (par exemple, événement prêt pour le DOM)
99
andr111

Il y a quelques bibliothèques, mais je ne les ai pas utilisées dans de grands projets. Vous voudrez peut-être les essayer:

-

Cependant, je pense que c'est quelque chose d'assez simple pour que vous puissiez l'essayer vous-même. Personnellement, je l'ai fait exactement quand j'avais besoin de le faire. Vous pouvez également créer une bibliothèque simple qui répond à vos besoins.

1. Exécutez les méthodes JS à partir d’Objective-C

Ce n'est vraiment qu'une ligne de code.

NSString *returnvalue = [webView stringByEvaluatingJavaScriptFromString:@"your javascript code string here"];

Plus de détails sur la documentation officielle UIWebView Documentation .

2. Exécuter les méthodes Objective-C à partir de JS

C'est malheureusement un peu plus complexe, car il n'y a pas la même propriété windowScriptObject (et la même classe) que Mac OSX, ce qui permet une communication complète entre les deux.

Cependant, vous pouvez facilement appeler à partir d'URL personnalisées javascript, telles que:

window.location = yourscheme://callfunction/parameter1/parameter2?parameter3=value

Et l'intercepter d'Objective-C avec ceci:

- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
   NSURL *URL = [request URL]; 
   if ([[URL scheme] isEqualToString:@"yourscheme"]) {
       // parse the rest of the URL object and execute functions
   } 
}

Ce n’est pas aussi propre qu’il devrait l’être (ni en utilisant windowScriptObject), mais cela fonctionne.

3. Écoutez les événements JS natifs d'Objective-C (par exemple, événement prêt pour le DOM)

D'après l'explication ci-dessus, vous voyez que si vous voulez faire cela, vous devez créer du code JavaScript, le joindre à l'événement que vous souhaitez surveiller et appeler le bon appel window.location à intercepter.

Encore une fois, pas propre comme il se doit, mais cela fonctionne.

149
Folletto

La méthode suggérée pour appeler Objective C depuis JS dans la réponse acceptée n'est pas recommandée. Un exemple de problèmes: si vous effectuez deux appels consécutifs immédiats, l’un est ignoré (vous ne pouvez pas changer d’emplacement trop rapidement).

Je recommande l'approche alternative suivante:

function execute(url) 
{
  var iframe = document.createElement("IFRAME");
  iframe.setAttribute("src", url);
  document.documentElement.appendChild(iframe);
  iframe.parentNode.removeChild(iframe);
  iframe = null;
}

Vous appelez la fonction execute à plusieurs reprises et, chaque appel étant exécuté dans sa propre iframe, ils ne doivent pas être ignorés lorsqu'ils sont appelés rapidement.

Crédits à ce gars .

57
talkol

Mise à jour: Cela a changé dans iOS 8. Ma réponse s'applique aux versions précédentes.

Une alternative, qui peut vous faire rejeter de la boutique d'applications, est d'utiliser WebScriptObject.

Ces API sont publiques sur OSX mais pas sur iOS.

Vous devez définir des interfaces avec les classes internes.

@interface WebScriptObject: NSObject
@end

@interface WebView
- (WebScriptObject *)windowScriptObject;
@end

@interface UIWebDocumentView: UIView
- (WebView *)webView;
@end

Vous devez définir votre objet qui va servir de WebScriptObject

@interface WebScriptBridge: NSObject
- (void)someEvent: (uint64_t)foo :(NSString *)bar;
- (void)testfoo;
+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
+ (WebScriptBridge*)getWebScriptBridge;
@end

static WebScriptBridge *gWebScriptBridge = nil;

@implementation WebScriptBridge
- (void)someEvent: (uint64_t)foo :(NSString *)bar
{
    NSLog(bar);
}

-(void)testfoo {
    NSLog(@"testfoo!");
}

+ (BOOL)isKeyExcludedFromWebScript:(const char *)name;
{
    return NO;
}

+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector;
{
    return NO;
}

+ (NSString *)webScriptNameForSelector:(SEL)sel
{
    // Naming rules can be found at: https://developer.Apple.com/library/mac/documentation/Cocoa/Reference/WebKit/Protocols/WebScripting_Protocol/Reference/Reference.html
    if (sel == @selector(testfoo)) return @"testfoo";
    if (sel == @selector(someEvent::)) return @"someEvent";

    return nil;
}
+ (WebScriptBridge*)getWebScriptBridge {
    if (gWebScriptBridge == nil)
        gWebScriptBridge = [WebScriptBridge new];

    return gWebScriptBridge;
}
@end

Maintenant, définissez cette instance sur votre UIWebView

if ([uiWebView.subviews count] > 0) {
    UIView *scrollView = uiWebView.subviews[0];

    for (UIView *childView in scrollView.subviews) {
        if ([childView isKindOfClass:[UIWebDocumentView class]]) {
            UIWebDocumentView *documentView = (UIWebDocumentView *)childView;
            WebScriptObject *wso = documentView.webView.windowScriptObject;

            [wso setValue:[WebScriptBridge getWebScriptBridge] forKey:@"yourBridge"];
        }
    }
}

Maintenant, à l'intérieur de votre javascript, vous pouvez appeler:

yourBridge.someEvent(100, "hello");
yourBridge.testfoo();
12
Joseph Lennox

Dans iOS8, vous pouvez regarder WKWebView au lieu de UIWebView . Cela a la classe suivante: WKScriptMessageHandler: fournit une méthode pour recevoir des messages de JavaScript s'exécutant dans une page Web.

5
Alex Stone
3
CocoaChris

Jetez un coup d’œil au projet KirinJS: Kirin JS qui permet d’utiliser Javascript pour la logique de l’application et une interface utilisateur native adaptée à la plate-forme sur laquelle il est exécuté.

0
rochal

Si vous utilisez WKWebView sur iOS 8, jetez un coup d'œil à XWebView , qui peut automatiquement exposer l'interface native à JavaScript.

0
soflare

J'ai créé une bibliothèque telle que WebViewJavascriptBridge, mais elle ressemble plus à JQuery, est plus facile à configurer et à utiliser. Ne comptez pas sur jQuery (bien que ce soit un crédit, si j'avais su que WebViewJavascriptBridge existait avant d'écrire cela, je me suis peut-être légèrement retenu avant de plonger). Laissez-moi savoir ce que vous pensez! jockeyjs

0
Tim Coulter

Votre meilleur pari est l’offre Appcelerators Titanium. Ils ont déjà construit un pont javascript Obj-C en utilisant le Moteur V8 Moteur JavascriptCore utilisé par webkit. Il est également open source, vous pourrez donc le télécharger et bricoler avec l'Obj-C à votre guise.

0
hova