说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

在Swift中使用JavaScript的方法和技巧

HTML文档下载 WORD文档下载 PDF文档下载
Nate Cook是一位独立的Web及移动应用开发者,是继Mattt大神后NSHipster的主要维护者,也是SwiftDoc.org创造者。在本文中,他介绍了在Swift中使用JavaScript的方法和技巧,对于iOS和Web工程师有着非常实用的价值。

本文作者Nate Cook是一位独立的Web及移动应用开发者,是继Mattt大神之后NSHipster的主要维护者,也是非常知名活跃的Swift博主,并且还是支持自动生成Swift在线文档的SwiftDoc.org网站创造者。在本文中,他介绍了在Swift中使用JavaScript的方法和技巧,对于iOS和Web应用工程师有着非常实用的价值,以下为译文:

在RedMonk发布的2015年1月编程语言排行榜中,Swift采纳率排名迅速飙升,从刚刚面世时的68位跃至22位,Objective-C仍然稳居TOP 10,而JavaScript则凭借着其在iOS平台上原生体验优势成为了年度最火热的编程语言。


而早在2013年苹果发布的OS X Mavericks和iOS 7两大系统中便均已加入了JavaScriptCore框架,能够让开发者轻松、快捷、安全地使用JavaScript语言编写应用。不论叫好叫骂,JavaScript霸主地位已成事实。开发者们趋之若鹜,JS工具资源层出不穷,用于OS X和iOS系统等高速虚拟机也蓬勃发展起来。

JSContext/JSValue

JSContext即JavaScript代码的运行环境。一个Context就是一个JavaScript代码执行的环境,也叫作用域。当在浏览器中运行JavaScript代码时,JSContext就相当于一个窗口,能轻松执行创建变量、运算乃至定义函数等的JavaScript代码:

//Objective-CJSContext *context = [[JSContext alloc] init];[context evaluateScript:@"var num = 5 + 5"];[context evaluateScript:@"var names = ['Grace', 'Ada', 'Margaret']"];[context evaluateScript:@"var triple = function(value) { return value * 3 }"];JSValue *tripleNum = [context evaluateScript:@"triple(num)"];

//Swiftlet context = JSContext()context.evaluateScript("var num = 5 + 5")context.evaluateScript("var names = ['Grace', 'Ada', 'Margaret']")context.evaluateScript("var triple = function(value) { return value * 3 }")let tripleNum: JSValue = context.evaluateScript("triple(num)")

像JavaScript这类动态语言需要一个动态类型(Dynamic Type), 所以正如代码最后一行所示,JSContext里不同的值均封装在JSValue对象中,包括字符串、数值、数组、函数等,甚至还有Error以及null和undefined。

JSValue包含了一系列用于获取Underlying Value的方法,如下表所示:

JavaScript Type
JSValue method
Objective-C Type
Swift Type
string
toString
NSString
String!
boolean
toBool
BOOL
Bool
number
toNumber
toDouble
toInt32
toUInt32
NSNumber
double
int32_t
uint32_t
NSNumber!
Double
Int32
UInt32
Date toDate
NSDate
NSDate!
Array
toArray
NSArray
[AnyObject]!
Object
toDictionary
NSDictionary
[NSObject : AnyObject]!
Object
toObject
toObjectOfClass:
custom type
custom type
想要检索上述示例中的tripleNum值,只需使用相应的方法即可:

//Objective-CNSLog(@"Tripled: %d", [tripleNum toInt32]);// Tripled: 30
//Swiftprintln("Tripled: \(tripleNum.toInt32())")// Tripled: 30
下标值(Subscripting Values)

通过在JSContext和JSValue实例中使用下标符号可以轻松获取上下文环境中已存在的值。其中,JSContext放入对象和数组的只能是字符串下标,而JSValue则可以是字符串或整数下标。

//Objective-CJSValue *names = context[@"names"];JSValue *initialName = names[0];NSLog(@"The first name: %@", [initialName toString]);// The first name: Grace
//Swiftlet names = context.objectForKeyedSubscript("names")let initialName = names.objectAtIndexedSubscript(0)println("The first name: \(initialName.toString())")// The first name: Grace
而Swift语言毕竟才诞生不久,所以并不能像Objective-C那样自如地运用下标符号,目前,Swift的方法仅能实现objectAtKeyedSubscript()和objectAtIndexedSubscript()等下标。

函数调用(Calling Functions)

我们可以将Foundation类作为参数,从Objective-C/Swift代码上直接调用封装在JSValue的JavaScript函数。这里,JavaScriptCore再次发挥了衔接作用。

//Objective-CJSValue *tripleFunction = context[@"triple"];JSValue *result = [tripleFunction callWithArguments:@[@5] ];NSLog(@"Five tripled: %d", [result toInt32]);
//Swiftlet tripleFunction = context.objectForKeyedSubscript("triple")let result = tripleFunction.callWithArguments([5])println("Five tripled: \(result.toInt32())")
异常处理(Exception Handling)

JSContext还有一个独门绝技,就是通过设定上下文环境中exceptionHandler的属性,可以检查和记录语法、类型以及出现的运行时错误。exceptionHandler是一个回调处理程序,主要接收JSContext的reference,进行异常情况处理。

//Objective-Ccontext.exceptionHandler = ^(JSContext *context, JSValue *exception) {   NSLog(@"JS Error: %@", exception);};[context evaluateScript:@"function multiply(value1, value2) { return value1 * value2 "];// JS Error: SyntaxError: Unexpected end of script
//Swiftcontext.exceptionHandler = { context, exception in    println("JS Error: \(exception)")}context.evaluateScript("function multiply(value1, value2) { return value1 * value2 ")// JS Error: SyntaxError: Unexpected end of script

JavaScript函数调用

了解了从JavaScript环境中获取不同值以及调用函数的方法,那么反过来,如何在JavaScript环境中获取Objective-C或者Swift定义的自定义对象和方法呢?要从JSContext中获取本地客户端代码,主要有两种途径,分别为Blocks和JSExport协议。

  • Blocks (块)

在JSContext中,如果Objective-C代码块赋值为一个标识符,JavaScriptCore就会自动将其封装在JavaScript函数中,因而在JavaScript上使用Foundation和Cocoa类就更方便些——这再次验证了JavaScriptCore强大的衔接作用。现在CFStringTransform也能在JavaScript上使用了,如下所示:

//Objective-Ccontext[@"simplifyString"] = ^(NSString *input) {   NSMutableString *mutableString = [input mutableCopy];   CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformToLatin, NO);   CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, NO);   return mutableString;};NSLog(@"%@", [context evaluateScript:@"simplifyString('안녕하새요!')"]);
//Swiftlet simplifyString: @objc_block String -> String = { input in    var mutableString = NSMutableString(string: input) as CFMutableStringRef    CFStringTransform(mutableString, nil, kCFStringTransformToLatin, Boolean(0))    CFStringTransform(mutableString, nil, kCFStringTransformStripCombiningMarks, Boolean(0))    return mutableString}context.setObject(unsafeBitCast(simplifyString, AnyObject.self), forKeyedSubscript: "simplifyString")println(context.evaluateScript("simplifyString('안녕하새요!')"))// annyeonghasaeyo!
需要注意的是,Swift的speedbump只适用于Objective-C block,对Swift闭包无用。要在一个JSContext里使用闭包,有两个步骤:一是用@objc_block来声明,二是将Swift的knuckle-whitening unsafeBitCast()函数转换为 AnyObject。

  • 内存管理(Memory Management)

代码块可以捕获变量引用,而JSContext所有变量的强引用都保留在JSContext中,所以要注意避免循环强引用问题。另外,也不要在代码块中捕获JSContext或任何JSValues,建议使用[JSContext currentContext]来获取当前的Context对象,根据具体需求将值当做参数传入block中。

17173总经理赵佳:媒体移动化需抓住三大要素 Django 1.6发布 支持持久数据库链接 如何优化单页面网站搜索引擎? TechCrunch国际创新峰会将于上海举行 极路由:一场由路由器引发的概念盛宴 14nm制程:三星64bit处理器 Exynos 6/S曝光 从Oracle到MySQL,余额宝云实践分享 从南水北调东线工程看物联网,大数据的另一面 不只是技术!成为IT经理必备的十大软技能 看看传说5亿行代码的Healthcare.gov网站的架构 如何走出选择PHP还是ASP.NET的两难境地? 你的设计够档次吗?分享25个奇异的404页面 百度LBS推Openmap战略:无编程经验者可通过拖拽制作个性化地图应用 百万用户时尚分享网站feed系统扩展实践 Twitter上市首战告捷的四大因素 大幕将启!MDCC2013移动开发者大会下周召开 TUP第30期:微软资深专家论如何用Visual Studio开发iOS、Android应用 [开源推荐]Riot.js:不足1KB的MVP客户端框架 研发周报:最难忘的Bug调试经历 NSA如何侵入Google和雅虎的私有数据网络? 飞天5K:开放比开源更有意义 MDCC之移动娱乐游戏峰会:手游金玩奖即将揭晓 开源巨人火狐浏览器:9周岁生日快乐! 感受OpenStack Summit香港大会 渣打科营中心:创建以技术为核心的企业文化 抱怨IT公司人才缺乏?留住现有人才方是正途 专访Esri中国区技术总监:打造新一代WebGIS平台 TIOBE 2013年11月编程语言排行榜:C#、Transact-SQL及VB.NET厚积薄发 透过KitKat,Android或与ChromeOS融合? 利用Spring Data Neo4j搭建推荐系统 七丽借百度SiteApp移动化 分发及变现能力获大幅提升 如何用ASP上传文件到数据库、读取并下载? 100分求教我的ActiveForm出现access violation at address...的问题(急急急) 最真诚的祝福大力和璇玑! 控制文件损坏,恢复是碰到了难点--ora-00600错误。怎么办??? 请问WebBrowser对象在弹出式窗口中是不是不能用? 关于CListCtrl的一个问题 多个cpp可以有多个main吗? 怎么样在不同分辨率下显示同一网页不变形? 卡拉OK厅中的男人和女人们(zt) 怎么在一个接口中调用另外一个接口 大力过来 帮忙! 论坛里有保留cookies的功能,但是有些用户说cookies保存不了 大家好!我有问题很急呀!!! 哪个函数可以打开多个文件? 大家请进来说说吧,用什么软件编辑jsp和javascript能测试出网页中提示的:完成,但网页上有错误,这种错误所在的行和具体的什么错误。 关于在课件项目中应用XML的问题,回复心得或相关链接都有赠分 多个附件上传和下载 VB.NET中樹是怎樣展開 我可以把ACCESS数据库的表导出到SQL SERVER中吗? 图片存在目录与存在数据库各有什么优缺点呢? 点击这个框架中的网页能够打印另一个框架中的内容吗 求救~!!!! 请问如何将台式机硬盘上的内容copy到笔记本的硬盘上?? ADO数据集的服务器游标的使用问题 为什么我在发布Delphi程序时总出现Error1324错误 快来救救我的硬盘呀 mydatastore.update() 返回 -1 如何知道出什么错? 如何获得当前光标所在程序的edit框的handle? [ 请教 ] 关于FREE风格的数据窗口的显示问题! 这个存储过程怎么写呀? 如何添加新函数?急!急!急! 我在网上把一副图片设为背景,我不知道他的文件名,我现在想把它找出来,请问如何办到。在右键-属性-背景中他的名称是“Internet Explo 请高手指点。 vb函数使用的问题 简单两台机对连问题 做斑竹、做会员就可以领工资(RMB)! jsp中session跨war包调用问题 PB画图问题 请各位搞WEB挖掘的朋友都留个联系方式 如何指定 记录集的游标类型,大侠请进,小弟急用(内附代码)!!! 请投上一票! mssql一个很奇怪的问题,如何解决啊!“键列信息不足或不正确,更新影响到多行” 天杀的3721,大家进来共同讨伐这有史以来最恶心的XXX,进来都有分 c写的cgi怎么获得表单中某个下拉菜单的value和text.在线等 哪有VC的SP5下载? 要实现这样的功能,SQL该如何写(急,在线等待)? 哪里可以找到string.format的格式说明啊? 【无限祝福】:璇玑、大力相知相伴 查找数据库的问题。。。。。 在asp.net中怎么调用第二个窗体呀???请教大家帮我。thanks ,中秋快乐 人体都有哪些病菌 事出无常必有妖具体是什么意思? 有《呐喊》中的经典片段吗?带赏析 50字以内 大概10段 鲁迅的《呐喊》有哪些经典片段,50字,要分析的,我要4个, 中的优美段落少一点的,50个字左右,也要写得好一点的 房子前面有一片竹林,风水好不好?该如何化解? 两个完全相同的小金属球,它们所带电荷量之比为5:1,它们在相距一定距离(带电小球皆可视为点电荷)时相互作用力为F1,如果让它们接触后再放回原处,此时相互作用力变为F2,则F1:F2可能为? 养什么植物?(做叶绿体试验)我要搞一个课题,做实验,关于叶绿体光合作用的,怕到冬天摘不到树叶,想在室内养植物要求:叶多,光合作同强,生长快等请问我养什么植物好?对了,我在北方, 求诗《穆放》全文,说的是佛把我变成你必经路旁的一棵树. 我在佛前苦苦求了五千年,只求佛将我变做一棵树,等待着你的经过请问这是那首诗里的句子. 什么是偏振分束器这是光盘驱动器中光头部分的一个部件,它有什么功能? 旧金山地方检察院举行反家暴妇女维权座澳大利亚赏鲸季来临 民众目睹2600日本学生12万粒杏仁膏立体再现法国印澳夫妇因非法改建房屋供学生住宿被罚3美国50州首富名单出笼 盖茨巴菲特仍墨尔本赛马节下周将开始 预报称天气状联合国首次主动攻击非洲叛军 或抛弃被叙总统要求西方为日内瓦会议停止资助叙新书显示挪威杀人魔在母亲逝世前曾向其旅游局:明年节假日方案仍在研究 将参以色列批准新建1500套定居点住房遭美国研究生留学如何写好学习计划?56平蓝色小窝,保证让你眼前一亮!内乡法院少审法官张珂与灌涨法庭荣获南杨柏线近百盏路灯不亮 黑漆漆一片让人自然医学APP,打造行业专业应用平台这世上唯一能和中国大妈匹敌的,恐怕只浩泽再次登陆央视 《美丽家园》赞其智货车失控飞跃深沟冲入民房安徽一男子在家中燃爆汽油桶 欲与邻居湖南零陵一政协副主席违规为儿子办婚宴“魅力水城,绿色迁安”彰显城市转型大极度兽魂兼职掌柜独行剑神特种兵王叱咤异界留学仙界都市之唯一炼药师时空叛变七城联盟问鼎诸武都市之君临天下最妙仙路青海师范大学旅游拉萨德吉孤儿院旅游三国新城遗址旅游灰腾锡勒天然植物园旅游兴隆热带药用植物园旅游白沙门旅游娱乐园旅游陕西大寺旅游国际园博园旅游古市楼旅游绳武楼旅游观海园旅游
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn 说三道四技术文摘