2010-02-18 7 views
13

Su Windows, quando il controllo ActiveX "Shell.Explorer" è incorporato in un'applicazione è possibile registrare un gestore "esterno" - su un oggetto che implementa IDispatch, in modo tale che gli script nella pagina Web possano richiamare l'applicazione di hosting .Webkit incorporato - callback di script come?

<button onclick="window.external.Test('called from script code')">test</button> 

Ora, Ive si trasferì a sviluppo Mac e pensavo di poter ottenere qualcosa di simile di lavoro da parte di WebKit incorporato nella mia applicazione Cocoa. Ma sembra che non ci sia alcuna possibilità di consentire agli script di richiamare l'applicazione di hosting.

Un consiglio era di agganciare window.alert e ottenere script per passare una stringa di messaggio formattata come stringa di avviso. Mi chiedo anche se WebKit può essere indirizzato a un plug-in NPAPI ospitato dall'applicazione utilizzando NPPVpluginScriptableNPObject.

Mi manca qualcosa? È davvero così difficile ospitare una WebView e consentire agli script di interagire con l'host?

risposta

30

È necessario implementare i vari metodi del protocollo WebScripting. Ecco un esempio di base:

@interface WebController : NSObject 
{ 
    IBOutlet WebView* webView; 
} 

@end 

@implementation WebController 

//this returns a nice name for the method in the JavaScript environment 
+(NSString*)webScriptNameForSelector:(SEL)sel 
{ 
    if(sel == @selector(logJavaScriptString:)) 
     return @"log"; 
    return nil; 
} 

//this allows JavaScript to call the -logJavaScriptString: method 
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)sel 
{ 
    if(sel == @selector(logJavaScriptString:)) 
     return NO; 
    return YES; 
} 

//called when the nib objects are available, so do initial setup 
- (void)awakeFromNib 
{ 
    //set this class as the web view's frame load delegate 
    //we will then be notified when the scripting environment 
    //becomes available in the page 
    [webView setFrameLoadDelegate:self]; 

    //load a file called 'page.html' from the app bundle into the WebView 
    NSString* pagePath = [[NSBundle mainBundle] pathForResource:@"page" ofType:@"html"]; 
    NSURL* pageURL = [NSURL fileURLWithPath:pagePath]; 
    [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:pageURL]]; 
} 


//this is a simple log command 
- (void)logJavaScriptString:(NSString*) logText 
{ 
    NSLog(@"JavaScript: %@",logText); 
} 

//this is called as soon as the script environment is ready in the webview 
- (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowScriptObject forFrame:(WebFrame *)frame 
{ 
    //add the controller to the script environment 
    //the "Cocoa" object will now be available to JavaScript 
    [windowScriptObject setValue:self forKey:@"Cocoa"]; 
} 

@end 

Dopo l'implementazione di questo codice nel vostro controller, è ora possibile chiamare Cocoa.log('foo'); dall'ambiente Javascript e il metodo logJavaScriptString: sarà chiamato.

+0

Does [webView mainFrame] loadData: attiva il didClearWindowObject:? Ho il [webView setFrameLoadDelegate: self]; configurazione, ma questa non è la configurazione di windowScriptObject quando provo un breakpoint. – Luke

+1

L'ho eseguito in questo modo, ma come si chiama un gestore (funzione JS) da Cocoa, come una richiamata che qualcosa è successo in Cocoa. Ovviamente è possibile ottenere 'windowScriptObject' da' WebView', ma esiste un modo per 'Cocoa' di sapere a quale istanza' WebScriptObject' appartiene? –

+0

Ottimo. Grazie! ;-) –

1

Questo è molto facile da fare con lo WebScriptObject API in combinazione con il framework JavaScriptCore.

Problemi correlati