2014-09-11 33 views
18

In UIWebView, posso ottenere JSContext attraverso:Come ottenere JSContext da WKWebView

[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"] 

Allo stesso modo non funziona in WKWebView e si blocca app quando arriva questa riga di codice.

C'è un modo per ottenere JSContext in WKWebView?

grazie in anticipo.

+0

hai trovato qualche soluzione per JS ca llbacks? –

risposta

8

Non è possibile ottenere il contesto, poiché layout e javascript vengono gestiti su un altro processo.

Invece, aggiungi gli script alla configurazione della tua webview e imposta il controller di visualizzazione (o un altro oggetto) come gestore dei messaggi di script.

Ora, inviare messaggi da JavaScript in questo modo:

window.webkit.messageHandlers.interOp.postMessage(message) 

Il tuo gestore di messaggi di script riceverà una richiamata:

- (void)userContentController:(WKUserContentController *)userContentController 
          didReceiveScriptMessage:(WKScriptMessage *)message{ 
    NSLog(@"%@", message.body); 
} 
+0

sì, ho già usato questo metodo anche se l'associazione dell'oggetto nativo al contesto di js è più comoda per gestire il callback di js. Posso chiamare js callback tramite evaluateJavaScript – Xiong

+0

Assicurati di aprire un bug report. Apple può fare un po 'di magia nel mezzo e dare comunque la funzionalità. Dal momento che il progetto è open source, qualcuno potrebbe farlo e pubblicare una richiesta di pull. –

+0

Il lato negativo di questo è che non sembra essere un modo per ottenere informazioni sugli errori JavaScript che si verificano durante l'esecuzione. –

0

XWebView è una buona soluzione per il vostro problema. È in grado di stabilire un ponte tra nativo e JS e fornire un'API in stile vincolante.

+0

Sembra davvero interessante, ma solo iOS, solo fyi ... – shmim

+0

Ma non concede l'accesso a Javascriptcore – NaveenKumar

+0

In effetti, è impossibile accedere al JSContext di un WKWebView perché è nel processo di rendering anziché nel processo di App. – soflare

1

Configurazione wkwebview come questo e aggiungere gestore di conseguenza e messaggio di posta dallo script nel modello simile

NSString *myScriptSource = @"alert('Hello, World!')"; 


WKUserScript *s = [[WKUserScript alloc] initWithSource:myScriptSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]; 
WKUserContentController *c = [[WKUserContentController alloc] init]; 
[c addUserScript:s]; 
// Add a script message handler for receiving "buttonClicked" event notifications posted from the JS document using window.webkit.messageHandlers.buttonClicked.postMessage script message 
[c addScriptMessageHandler:self name:@"buttonClicked"]; 

WKWebViewConfiguration *conf = [[WKWebViewConfiguration alloc] init]; 
conf.userContentController = c; 

WKWebView *webview = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:conf]; 
[self.view addSubview:webview]; 
webview.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 
// Do any additional setup after loading the view, typically from a nib. 
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]]; 
[webview loadRequest:request]; 

implementare script di gestore di messaggi "WKScriptMessageHandler" con il nome del metodo

#pragma mark -WKScriptMessageHandler 
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message   { 
if ([message.name isEqualToString:@"buttonClicked"]) { 
self.buttonClicked ++; 
} 

// JS objects are automatically mapped to ObjC objects 
id messageBody = message.body; 
if ([messageBody isKindOfClass:[NSDictionary class]]) { 
NSString* idOfTappedButton = messageBody[@"ButtonId"]; 
[self updateColorOfButtonWithId:idOfTappedButton]; 
} 
} 

e inviare il modulo di messaggio js like this

var button = document.getElementById("clickMeButton"); 
button.addEventListener("click", function() { 
    var messgeToPost = {'ButtonId':'clickMeButton'}; 
    window.webkit.messageHandlers.buttonClicked.postMessage(messgeToPost); 
},false);