it-swarm.com.de

iOS JavaScript-Brücke

Ich arbeite an einer App, bei der ich sowohl HTML5 in UIWebView als auch das native iOS-Framework gemeinsam verwenden werde. Ich weiß, dass ich die Kommunikation zwischen JavaScript und Objective-C implementieren kann. Gibt es Bibliotheken, die die Implementierung dieser Kommunikation vereinfachen? Ich weiß, dass es mehrere Bibliotheken gibt, um native iOS-Apps in HTML5 und Javascript zu erstellen (beispielsweise AppMobi, PhoneGap). Ich bin jedoch nicht sicher, ob es eine Bibliothek gibt, mit der native iOS-Apps mit starkem JavaScript-Einsatz erstellt werden können. Ich muss einfach:

  1. Führen Sie JS-Methoden aus Objective-C aus
  2. Führen Sie Objective-C-Methoden von JS aus aus
  3. Hören Sie native JS-Ereignisse von Objective-C (zum Beispiel DOM-ready-Ereignis).
99
andr111

Es gibt einige Bibliotheken, aber ich habe keine davon in großen Projekten verwendet. Vielleicht möchten Sie sie auch ausprobieren:

-

Ich denke jedoch, dass es einfach genug ist, dass Sie es selbst versuchen könnten. Ich habe genau das gemacht, als ich das brauchte. Sie können auch eine einfache Bibliothek erstellen, die Ihren Anforderungen entspricht.

1. Führen Sie JS-Methoden aus Objective-C aus

Das ist wirklich nur eine Codezeile.

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

Weitere Details zur offiziellen UIWebView-Dokumentation .

2. Führen Sie Objective-C-Methoden von JS aus aus

Dies ist leider etwas komplexer, da unter Mac OSX nicht die gleiche windowScriptObject-Eigenschaft (und Klasse) vorhanden ist, die eine vollständige Kommunikation zwischen den beiden ermöglicht.

Sie können jedoch von Javascript aus benutzerdefinierte URLs aufrufen, z.

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

Und fangen Sie mit Objective-C ab:

- (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
   } 
}

Dies ist nicht so sauber, wie es sein sollte (oder mit windowScriptObject), aber es funktioniert.

3. Hören Sie native JS-Ereignisse von Objective-C ab (z. B. DOM ready-Ereignis)

Anhand der obigen Erklärung sehen Sie, dass Sie, wenn Sie dies tun möchten, JavaScript-Code erstellen, ihn an das Ereignis anhängen müssen, das Sie überwachen möchten, und den richtigen window.location-Aufruf aufrufen, um ihn abzufangen.

Wieder nicht sauber, wie es sein sollte, aber es funktioniert.

149
Folletto

Die vorgeschlagene Methode zum Aufrufen von Objective C aus JS in der akzeptierten Antwort wird nicht empfohlen. Ein Beispiel für Probleme: Wenn Sie zwei unmittelbar aufeinander folgende Anrufe tätigen, wird einer ignoriert (Sie können den Standort nicht zu schnell wechseln).

Ich empfehle den folgenden alternativen Ansatz:

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

Sie rufen die Funktion execute wiederholt auf. Da jeder Aufruf in seinem eigenen Iframe ausgeführt wird, sollten sie bei einem schnellen Aufruf nicht ignoriert werden.

Kredite an diesen Kerl .

57
talkol

Update: Dies hat sich in iOS 8 geändert. Meine Antwort gilt für frühere Versionen.

Eine Alternative, die dazu führen kann, dass Sie vom App Store abgelehnt werden, ist die Verwendung von WebScriptObject.

Diese APIs sind unter OSX öffentlich, nicht jedoch unter iOS.

Sie müssen Schnittstellen zu den internen Klassen definieren.

@interface WebScriptObject: NSObject
@end

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

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

Sie müssen Ihr Objekt definieren, das als WebScriptObject dienen soll

@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

Legen Sie nun eine Instanz auf Ihre UIWebView fest

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"];
        }
    }
}

Jetzt können Sie in Ihrem Javascript Folgendes anrufen:

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

In iOS8 können Sie WKWebView anstelle von UIWebView anzeigen. Diese hat die folgende Klasse: WKScriptMessageHandler: Stellt eine Methode zum Empfangen von Nachrichten von JavaScript bereit, das auf einer Webseite ausgeführt wird.

5
Alex Stone
3
CocoaChris

Schauen Sie sich das KirinJS-Projekt an: Kirin JS , das die Verwendung von Javascript für die Anwendungslogik und die native Benutzeroberfläche ermöglicht, die der Plattform entspricht, auf der es ausgeführt wird.

0
rochal

Wenn Sie WKWebView unter iOS 8 verwenden, werfen Sie einen Blick auf XWebView , das die native Schnittstelle automatisch für Javascript verfügbar machen kann.

0
soflare

Ich habe eine Bibliothek wie WebViewJavascriptBridge erstellt, aber sie ist eher JQuery-ähnlich, lässt sich einfacher einrichten und ist einfacher zu verwenden. Verlässt sich nicht auf jQuery (obwohl ich vorher gewusst hatte, dass WebViewJavascriptBridge existierte, bevor ich das schrieb, habe ich mich vielleicht etwas zurückgehalten, bevor ich eintauchte). Lass mich wissen was du denkst! Jockeyjs

0
Tim Coulter

Ihre beste Wette ist Appcelerators Titanium. Sie haben bereits eine Obj-C-Javascript-Brücke mit der V8-Motor JavascriptCore-Engine, die vom Webkit verwendet wird. Es ist auch Open Source, so dass Sie es herunterladen und mit dem Obj-C nach Belieben basteln können.

0
hova