首页 > 白话Cocoa > 浏览器开发第二篇,javascript与objective c的交互

浏览器开发第二篇,javascript与objective c的交互

现在很多视频或者音乐的客户端,比如QQMusic For Mac。往往通过在客户端嵌入网页的方式来展现内容,并通过js调用客户端的一些功能,比如下载该视频或者播放音乐等。嵌入网页基本都是采用网页控件来展示网页。这时可以把客户端看成是包含了一个小型浏览器的客户端。用嵌入网页的方式,好处是显然的,一是网页可以轻易做出很炫丽的效果,当然客户端通过艰难的自绘也可以做出很华丽的效果,但开发时间跟开发难度跟网页比起来没得比。二是,网页可以随时更改,更改后可以实时更新到你发出去的每一个客户端版本,这一种扩展性在实战中是很重要的。以前参与过一个播放量超过3000万的视频客户端项目,一开始30%的区域用客户端来显示,而客户端的代码都是打包到每一个版本的,一开始项目会考虑一些兼容性问题,但实际上很难在第一版本全部都考虑到,导致新的的版本的一些更改无法更新到旧的版本。为了让扩展性更好,该项目演变到后面,改成只有10%区域采用客户端,其它区域全部用嵌入网页的方式,包括视频播放页,也是在一个窗口里面嵌入一个页面,该页面包含一个占满窗口内容并自适应窗口大小的flash。

javascript与objective交互,双方是对等的。也就是javascript应该可以调用objective c;同时反过来objective c应该也可以调用javascript。

一、javascript调用objective c

     /* 当页面加载完成,将要执行javascript之前,windowScriptObjectAvailable消息将会发送给web view 的frame load delegate。我们可以在这个最完美的时机里面,设置一个属于我们自己的javascript对象

     */
- (void)webView:(WebView *)webView windowScriptObjectAvailable:(WebScriptObject *)windowScriptObject {
     NSLog(@"%@ received %@", self, NSStringFromSelector(_cmd));


    /*我们将当前对象加到javascript里面的window全局对象里面,并命名为console。之后可以在javascript通过使用console变量来使用当前的对象*/
    [windowScriptObject setValue:self forKey:@"console"];


}



//isSelectorExcludedFromWebScript方法定义了哪些函数可以暴露给javascript调用,返回NO,表示该方法可以被外部的javascript调用。

+ (BOOL)isSelectorExcludedFromWebScript:(SEL)selector {
     NSLog(@"%@ received %@ for '%@'", self, NSStringFromSelector(_cmd), NSStringFromSelector(selector));
    if (selector == @selector(doOutputToLog:)
     || selector == @selector(changeJavaScriptText:)
     || selector == @selector(reportSharedValue)) {
        return NO;
    }
    return YES;
}



//webScriptNameForSelector方法被webview调用,定义了javascript调用objective c的方法时,方法名与我们objective c内部方法名的映射关系。
//如下所示,当javascript调用console.log()时,相当于调用objective c当前对象的doOutputToLog函数
+ (NSString *) webScriptNameForSelector:(SEL)sel {
     NSLog(@"%@ received %@ with sel='%@'", self, NSStringFromSelector(_cmd), NSStringFromSelector(sel));
     
    if (sel == @selector(doOutputToLog:)) {
          //注意:javascript是没有重载函数的,虽然在这里我们的objective c方法有一个参数,但跟javascript函数映射的时候,只需要指明javascript函数的名字就行,因为该名字在javascript里面对应的函数是惟一的。
          return @"log";
    } else if (sel == @selector(changeJavaScriptText:)) {
          return @"setscript";
     } else {
          return nil;
     }
}



//isKeyExcludedFromWebScript方法将被web view调用,定义哪些变量可以与javascript共享被javascript调用,返回NO表示可以被javascript共享。
//如下所示,当javascript调用console.sharedValue时,相当于调用当前对象的sharedValue成员变量
+ (BOOL)isKeyExcludedFromWebScript:(const char *)property {

     NSLog(@"%@ received %@ for '%s'", self, NSStringFromSelector(_cmd), property);
     if (strcmp(property, "sharedValue") == 0) {
        return NO;
    }
    return YES;
}

二、objective c调用javascript,主要有两种场景

1、objective c 执行一段javascript代码
使用下面的函数

- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

2、objective c 调用html页面里面的javascript函数

2.1 js端有一个函数SampleFunction:


function SampleFunction( parameterOne, parameterTwo ) {
     document.getElementById('one').innerText = parameterOne;

     document.getElementById('two').innerText = parameterTwo;
     return 'done!';
}

2.2 objective c端可以用下面的方法来调用:


//paramOne, paramTwo, callResult是三个NSTextField变量
- (IBAction)callJavaScriptWithParameters:(id)sender {
     NSLog(@"%@ received %@", self, NSStringFromSelector(_cmd));
    
     /* set up the function arguments */
     NSArray* args = [NSArray arrayWithObjects:
               [paramOne stringValue],
               [paramTwo stringValue],
               nil];


     /* call the javascript function named SampleFunction */
     [callResult setStringValue:
          [[theWebView ] callWebScriptMethod:@"SampleFunction" withArguments:args]];
}

三、关于javascript里面的alert

如果我们设置了WebUIDelegate代理,当javascript执行alert的时候,runJavaScriptAlertPanelWithMessage消息将会发送给代理,我们可以在里面打log进行调试。或者可以自定义一个对话框,然后把信息展示给用户。

- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message {
     NSLog(@"%@ received %@ with '%@'", self, NSStringFromSelector(_cmd), message);
}

四、官方有一个demo,包含了上面所述的所有技术细节。源代码地址:
https://developer.apple.com/library/mac/samplecode/CallJS/Introduction/Intro.html

(转载本站文章请注明出处 www.helloitworks.com ,请勿用于任何商业用途)

分类: 白话Cocoa 标签: ,
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.