在Swift中使用JavaScript的方法和技巧.docx_第1页
在Swift中使用JavaScript的方法和技巧.docx_第2页
在Swift中使用JavaScript的方法和技巧.docx_第3页
在Swift中使用JavaScript的方法和技巧.docx_第4页
在Swift中使用JavaScript的方法和技巧.docx_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

重庆仁人在Swift中使用JavaScript的方法和技巧本文作者Nate Cook是一位独立的Web及移动应用开发者,是继Mattt大神之后NSHipster的主要维护者,也是非常知名活跃的Swift博主,并且还是支持自动生成Swift在线文档的SwiftD网站创造者。在本文中,他介绍了在Swift中使用JavaScript的方法和技巧,对于iOS和Web应用工程师有着非常实用的价值,以下为译文:AD:本文作者Nate Cook是一位独立的Web及移动应用开发者,是继Mattt大神之后NSHipster的主要维护者,也是非常知名活跃的Swift博主,并且还是支持自动生成Swift在线文档的SwiftD网站创造者。在本文中,他介绍了在Swift中使用JavaScript的方法和技巧,对于iOS和Web应用工程师有着非常实用的价值,以下为译文:在RedMonk发布的2015年1月编程语言排行榜中,Swift采纳率排名迅速飙升,从刚刚面世时的68位跃至22位,Objective-C仍然稳居TOP10,而JavaScript则凭借着其在iOS平台上原生体验优势成为了年度最火热的编程语言。而早在2013年苹果发布的OS X Mavericks和iOS 7两大系统中便均已加入了JavaScriptCore框架,能够让开发者轻松、快捷、安全地使用JavaScript语言编写应用。不论叫好叫骂,JavaScript霸主地位已成事实。开发者们趋之若鹜,JS工具资源层出不穷,用于OSX和iOS系统等高速虚拟机也蓬勃发展起来。JSContext/JSValueJSContext即JavaScript代码的运行环境。一个Context就是一个JavaScript代码执行的环境,也叫作用域。当在浏览器中运行JavaScript代码时,JSContext就相当于一个窗口,能轻松执行创建变量、运算乃至定义函数等的JavaScript代码:/Objective-CJSContext*context=JSContextallocinit;contextevaluateScript:varnum=5+5;contextevaluateScript:varnames=Grace,Ada,Margaret;contextevaluateScript:vartriple=function(value)returnvalue*3;JSValue*tripleNum=contextevaluateScript:triple(num); /Swiftletcontext=JSContext()context.evaluateScript(varnum=5+5)context.evaluateScript(varnames=Grace,Ada,Margaret)context.evaluateScript(vartriple=function(value)returnvalue*3)lettripleNum:JSValue=context.evaluateScript(triple(num)像JavaScript这类动态语言需要一个动态类型(Dynamic Type), 所以正如代码最后一行所示,JSContext里不同的值均封装在JSValue对象中,包括字符串、数值、数组、函数等,甚至还有Error以及null和undefined。JSValue包含了一系列用于获取Underlying Value的方法,如下表所示:想要检索上述示例中的tripleNum值,只需使用相应的方法即可:/Objective-CNSLog(Tripled:%d,tripleNumtoInt32);/Tripled:30 /Swiftprintln(Tripled:(tripleNum.toInt32()/Tripled:30下标值(Subscripting Values)通过在JSContext和JSValue实例中使用下标符号可以轻松获取上下文环境中已存在的值。其中,JSContext放入对象和数组的只能是字符串下标,而JSValue则可以是字符串或整数下标。/Objective-CJSValue*names=contextnames;JSValue*initialName=names0;NSLog(Thefirstname:%,initialNametoString);/Thefirstname:Grace /Swiftletnames=context.objectForKeyedSubscript(names)letinitialName=names.objectAtIndexedSubscript(0)println(Thefirstname:(initialName.toString()/Thefirstname:Grace而Swift语言毕竟才诞生不久,所以并不能像Objective-C那样自如地运用下标符号,目前,Swift的方法仅能实现objectAtKeyedSubscript()和objectAtIndexedSubscript()等下标。函数调用(Calling Functions)我们可以将Foundation类作为参数,从Objective-C/Swift代码上直接调用封装在JSValue的JavaScript函数。这里,JavaScriptCore再次发挥了衔接作用。/Objective-CJSValue*tripleFunction=contexttriple;JSValue*result=tripleFunctioncallWithArguments:5;NSLog(Fivetripled:%d,resulttoInt32); /SwiftlettripleFunction=context.objectForKeyedSubscript(triple)letresult=tripleFunction.callWithArguments(5)println(Fivetripled:(result.toInt32()异常处理(Exception Handling)JSContext还有一个独门绝技,就是通过设定上下文环境中exceptionHandler的属性,可以检查和记录语法、类型以及出现的运行时错误。exceptionHandler是一个回调处理程序,主要接收JSContext的reference,进行异常情况处理。/Objective-Ccontext.exceptionHandler=(JSContext*context,JSValue*exception)NSLog(JSError:%,exception);contextevaluateScript:functionmultiply(value1,value2)returnvalue1*value2;/JSError:SyntaxError:Unexpectedendofscript/Swiftcontext.exceptionHandler=context,exceptioninprintln(JSError:(exception)context.evaluateScript(functionmultiply(value1,value2)returnvalue1*value2)/JSError:SyntaxError:UnexpectedendofscriptJavaScript函数调用了解了从JavaScript环境中获取不同值以及调用函数的方法,那么反过来,如何在JavaScript环境中获取Objective-C或者Swift定义的自定义对象和方法呢?要从JSContext中获取本地客户端代码,主要有两种途径,分别为Blocks和JSExport协议。Blocks (块)在JSContext中,如果Objective-C代码块赋值为一个标识符,JavaScriptCore就会自动将其封装在JavaScript函数中,因而在JavaScript上使用Foundation和Cocoa类就更方便些这再次验证了JavaScriptCore强大的衔接作用。现在CFStringTransform也能在JavaScript上使用了,如下所示:/Objective-CcontextsimplifyString=(NSString*input)NSMutableString*mutableString=inputmutableCopy;CFStringTransform(_bridgeCFMutableStringRef)mutableString,NULL,kCFStringTransformToLatin,NO);CFStringTransform(_bridgeCFMutableStringRef)mutableString,NULL,kCFStringTransformStripCombiningMarks,NO);returnmutableString;NSLog(%,contextevaluateScript:simplifyString(?!); /SwiftletsimplifyString:objc_blockString-String=inputinvarmutableString=NSMutableString(string:input)asCFMutableStringRefCFStringTransform(mutableString,nil,kCFStringTransformToLatin,Boolean(0)CFStringTransform(mutableString,nil,kCFStringTransformStripCombiningMarks,Boolean(0)returnmutableStringcontext.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中。JSExport协议借助JSExport协议也可以在JavaScript上使用自定义对象。在JSExport协议中声明的实例方法、类方法,不论属性,都能自动与JavaScrip交互。文章稍后将介绍具体的实践过程。JavaScriptCore实践我们可以通过一些例子更好地了解上述技巧的使用方法。先定义一个遵循JSExport子协议PersonJSExport的Person model,再用JavaScript在JSON中创建和填入实例。有整个JVM,还要NSJSONSerialization干什么?PersonJSExports和PersonPerson类执行的PersonJSExports协议具体规定了可用的JavaScript属性。,在创建时,类方法必不可少,因为JavaScriptCore并不适用于初始化转换,我们不能像对待原生的JavaScript类型那样使用var person = new Person()。/Objective-C/inPerson.h-classPerson;protocolPersonJSExportsproperty(nonatomic,copy)NSString*firstName;property(nonatomic,copy)NSString*lastName;propertyNSIntegerageToday;-(NSString*)getFullName;/createandreturnanewPersoninstancewithfirstNameandlastName+(instancetype)createWithFirstName:(NSString*)firstNamelastName:(NSString*)lastName;endinterfacePerson:NSObjectproperty(nonatomic,copy)NSString*firstName;property(nonatomic,copy)NSString*lastName;propertyNSIntegerageToday;end/inPerson.m-implementationPerson-(NSString*)getFullNamereturnNSStringstringWithFormat:%,self.firstName,self.lastName;+(instancetype)createWithFirstName:(NSString*)firstNamelastName:(NSString*)lastNamePerson*person=Personallocinit;person.firstName=firstName;person.lastName=lastName;returnperson;end/Swift/CustomprotocolmustbedeclaredwithobjcobjcprotocolPersonJSExports:JSExportvarfirstName:StringgetsetvarlastName:StringgetsetvarbirthYear:NSNumber?getsetfuncgetFullName()-String/createandreturnanewPersoninstancewithfirstNameandlastNameclassfunccreateWithFirstName(firstName:String,lastName:String)-Person/CustomclassmustinheritfromNSObjectobjcclassPerson:NSObject,PersonJSExports/propertiesmustbedeclaredasdynamicdynamicvarfirstName:StringdynamicvarlastName:StringdynamicvarbirthYear:NSNumber?init(firstName:String,lastName:String)self.firstName=firstNameself.lastName=lastNameclassfunccreateWithFirstName(firstName:String,lastName:String)-PersonreturnPerson(firstName:firstName,lastName:lastName)funcgetFullName()-Stringreturn(firstName)(lastName)配置JSContext创建Person类之后,需要先将其导出到JavaScript环境中去,同时还需导入Mustache JS库,以便对Person对象应用模板。/Objective-C/exportPersonclasscontextPerson=Personclass;/loadMustache.jsNSString*mustacheJSString=NSStringstringWithContentsOfFile:.encoding:NSUTF8StringEncodingerror:nil;contextevaluateScript:mustacheJSString; /Swift/exportPersonclasscontext.setObject(Person.self,forKeyedSubscript:Person)/loadMustache.jsifletmustacheJSString=String(contentsOfFile:.,encoding:NSUTF8StringEncoding,error:nil)context.evaluateScript(mustacheJSString)JavaScript数据&处理以下简单列出一个JSON范例,以及用JSON来创建新Person实例。注意:JavaScriptCore实现了Objective-C/Swift的方法名和JavaScript代码交互。因为JavaScript没有命名好的参数,任何额外的参数名称都采取驼峰命名法(Camel-Case),并附加到函数名称上。在此示例中,Objective-C的方法createWithFirstName:lastName:在JavaScript中则变成了createWithFirstNameLastName()。/JSONfirst:Grace,last:Hopper,year:1906,first:Ada,last:Lovelace,year:1815,first:Margaret,last:Hamilton,year:1936 /JavaScriptvarloadPeopleFromJSON=function(jsonString)vardata=JSON.parse(jsonString);varpeople=;for(i=0;idata.length;i+)varperson=Person.createWithFirstNameLastName(datai.first,datai.last);person.birthYear=datai.year;people.push(person);returnpeople;动手一试现在你只需加载JSON数据,并在JSContext中调用,将其解析到Person对象数组中,再用Mustache模板渲染即可:/Objective-C/getJSONstringNSString*peopleJSON=NSStringstringWithContentsOfFile:.encoding:NSUTF8StringEncodingerror:nil;/getloadfunctionJSValue*load=contextloadPeopleFromJSON;/callwithJSONandconverttoanNSArrayJSValue*loadResult=loadcallWithArguments:peopleJSON;NSArray*people=loadResulttoArray;/getrenderingfunctionandcreatetemplateJSValue*mustacheRender=contextMustach

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论