今天分享下最近学习到的:在 Mac OS X 平台上,实现 Javascript 与 Objective-C 两种编程语言的交互机制。
你侬我侬,忒煞情多。
情多处热如火。
把一块泥,捻一个你,
塑一个我,将咱两个,
一齐打破,用水调和,
再捻一个你,再塑一个我。
我泥中有你,你泥中有我,
与你生同一个衾(qin),
死同一个椁(guo)。
背景
现在很多视频或者音乐的客户端,比如 QQ Music For Mac。往往通过在客户端嵌入网页的方式来展现内容,并通过 Javascript 调用客户端的一些功能,比如下载视频或者播放音乐等。
嵌入网页基本都是采用 WebView 控件来展示网页,这时客户端好像内嵌了一个微型的浏览器。
用嵌入网页的方式,好处是显然的:
网页可以轻易做出很炫丽的效果,当然客户端通过艰难的自绘也可以做出很华丽的效果,但开发时间跟开发难度跟网页比起来没得比。
网页可以随时更改,更改后可以实时更新到你发出去的每一个客户端版本,这种扩展性在实战中是很重要的。
Javascript 与 Objective-C 双方是对等的,也就是 JS 可以调用 OC,反过来 OC 也可以调用 JS。
Demo
官方例子: CallJS ,详细了介绍上面所述的所有技术细节。
你也可以在 GitHub 上直接下载我写的这个 Demo:JS-OC-Communicate-Tutorial
技术细节
类型转换
从 Demo 中可以看出,在 OC 与 JS 通信时,变量的类型会自动进行转换,基本类型都会自动转换,如 JS 中的 number、boolean 都会转换成 OC 中的 NSNumber 类型,而 String 类型会自动转换成 NSString 类型,JS 中的对象会转换成 WebScriptObject 对象,而相关的属性信息可以通过 Key-Value 的方法读取和写入。
OC 调用 JS:
1、OC 执行一段 JS 代码,使用下面的函数:
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
2、OC 调用 html 页面里面的 JS 函数
比如 js 端有一个函数 JSFunction:
function JSFunction(parameter)
{
//显示OC返回的值
document.getElementById('view').value = parameter;
//返回成功的消息
var result = {'message':'Web page has received msg!'};
return result;
}
OC 端可以用下面的方法来调用:
- (IBAction)doAction:(id)sender
{
//设置对象
WebScriptObject *result = [[self.webView windowScriptObject] callWebScriptMethod:@"JSFunction" withArguments:@[self.textField.stringValue]];
NSString *message = [result valueForKey:@"message"];
}
JS 调用 OC:
1 | /* 当页面加载完成,将要执行JS之前,didClearWindowObject 消息将会发送给 webview 的frameLoadDelegate。我们可以在这个最完美的时机里,设置一个属于我们自己的JS对象 |
JS 中代码如下:
1 | function CallNative() |
总结
利用 Javascript 与 Objective-C 的通信机制,可以通过 HTML、Javascript、CSS 等 Web 技术实现炫丽的 UI ,而通过原生 API 实现与本地相关的操作。这对于 OSX 平台上的桌面客户端开发者而言是大大的福音。