一、前言

在这个提倡敏捷开发和H5横行的年代,原生App内嵌入一些H5页面已经成为一种流行的趋势。一套H5页面就可以适配复杂的iOS和Android页面,大量节省了开发和维护时间,如果本来就有移动端网页,只需简单适配即可完成,那我们何乐而不为呢?苹果也顺应了潮流,在iOS7中提供了JavaScriptCore框架用来与网页中的JS进行交互。还有Facebook推出的React Native,也给跨平台开发提供了新的思路和解决方案,虽然目前它还不是很成熟。但作为一个开发者,对这些新技术的出现自然会感到无比的兴奋。本文主要介绍iOS开发中,Swift如何使用JavaScriptCore与网页中的JS进行交互。

下载地址:

Github:https://github.com/YanlongMa/SwiftJavaScriptCore
如果本Demo对您有帮助,请不要吝啬您的Start(⊙o⊙)哦。

二、JavaScriptCore中的类

  • JSContext:JSContext是JS的执行环境,通过evaluateScript()方法可以执行JS代码
  • JSValue:JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等
  • JSExport:JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,这样JS才能调用原生的API

三、交互方式主要有两种

一)、 在Swift中,通过JSContext直接执行JS代码

import JavaScriptCore    //记得导入JavaScriptCore

// 通过JSContext执行js代码
let context: JSContext = JSContext()
let result1: JSValue = context.evaluateScript("1 + 3")
print(result1) // 输出4 // 定义js变量和函数
context.evaluateScript("var num1 = 10; var num2 = 20;")
context.evaluateScript("function sum(param1, param2) { return param1 + param2; }") // 通过js方法名调用方法
let result2 = context.evaluateScript("sum(num1, num2)")
print(result2) // 输出30 // 通过下标来获取js方法并调用方法
let squareFunc = context.objectForKeyedSubscript("sum")
let result3 = squareFunc.callWithArguments([10, 20]).toString()
print(result3) // 输出30

二). 在Swift中通过JSContext注入模型,然后调用模型的方法

1. 首先定义定义协议SwiftJavaScriptDelegate 该协议必须遵守JSExport协议

@objc protocol SwiftJavaScriptDelegate: JSExport {

    // js调用App的微信支付功能 演示最基本的用法
func wxPay(orderNo: String) // js调用App的微信分享功能 演示字典参数的使用
func wxShare(dict: [String: AnyObject]) // js调用App方法时传递多个参数 并弹出对话框 注意js调用时的函数名
func showDialog(title: String, message: String) // js调用App的功能后 App再调用js函数执行回调
func callHandler(handleFuncName: String) }

2. 然后定义一个模型 该模型实现SwiftJavaScriptDelegate协议

@objc class SwiftJavaScriptModel: NSObject, SwiftJavaScriptDelegate {

    weak var controller: UIViewController?
weak var jsContext: JSContext? func wxPay(orderNo: String) { print("订单号:", orderNo) // 调起微信支付逻辑
} func wxShare(dict: [String: AnyObject]) { print("分享信息:", dict) // 调起微信分享逻辑
} func showDialog(title: String, message: String) { let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "确定", style: .Default, handler: nil))
self.controller?.presentViewController(alert, animated: true, completion: nil)
} func callHandler(handleFuncName: String) { let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("\(handleFuncName)")
let dict = ["name": "sean", "age": 18]
jsHandlerFunc?.callWithArguments([dict])
}
}

3. 然后使用WebView加载对应的网页,这里加载例子中的demo.html文件

func addWebView() {

    self.webView = UIWebView(frame: self.view.bounds)
self.view.addSubview(self.webView)
self.webView.delegate = self
self.webView.scalesPageToFit = true // 加载本地Html页面
let url = NSBundle.mainBundle().URLForResource("demo", withExtension: "html")
let request = NSURLRequest(URL: url!) // 加载网络Html页面 请设置允许Http请求
//let url = NSURL(string: "http://www.mayanlong.com");
//let request = NSURLRequest(URL: url!) self.webView.loadRequest(request)
}

4. 最后在webViewDidFinishLoad代理中将我们定义的模型注入到网页中,暴露给JS

func webViewDidFinishLoad(webView: UIWebView) {

    self.jsContext = webView.valueForKeyPath("documentView.webView.mainFrame.javaScriptContext") as! JSContext
let model = SwiftJavaScriptModel()
model.controller = self
model.jsContext = self.jsContext // 这一步是将SwiftJavaScriptModel模型注入到JS中,在JS就可以通过WebViewJavascriptBridge调用我们暴露的方法了。
self.jsContext.setObject(model, forKeyedSubscript: "WebViewJavascriptBridge") // 注册到本地的Html页面中
let url = NSBundle.mainBundle().URLForResource("demo", withExtension: "html")
self.jsContext.evaluateScript(try? String(contentsOfURL: url!, encoding: NSUTF8StringEncoding)) // 注册到网络Html页面 请设置允许Http请求
//let url = "http://www.mayanlong.com";
//let curUrl = self.webView.request?.URL?.absoluteString //WebView当前访问页面的链接 可动态注册
//self.jsContext.evaluateScript(try? String(contentsOfURL: NSURL(string: url)!, encoding: NSUTF8StringEncoding)) self.jsContext.exceptionHandler = { (context, exception) in
print("exception:", exception)
}
}

5. Swift与JS方法互相调用

JS调用Swift方法

WebViewJavascriptBridge.wxPay('TN20160526')

WebViewJavascriptBridge.wxShare({
'title' : '马燕龙个人博客',
'description' : '一个专注于编程的技术博客',
'url' : 'http://www.mayanlong.com'
}) WebViewJavascriptBridge.showDialogMessage('马燕龙个人博客', '一个专注于编程的技术博客')

Swift调用JS方法并传参

func callHandler(handleFuncName: String) {

    let jsHandlerFunc = self.jsContext?.objectForKeyedSubscript("\(handleFuncName)")
let dict = ["name": "sean", "age": 18]
jsHandlerFunc?.callWithArguments([dict])
}

这样,我们就实现了Swift与JS的交互了,Demo中给出了详细的代码,大家可以下载运行。

四、代码下载及效果图

下载地址:

Github:https://github.com/YanlongMa/SwiftJavaScriptCore
如果本Demo对您有帮助,请不要吝啬您的Start(⊙o⊙)哦。

效果图:

本文首发于马燕龙个人博客,欢迎分享,转载请标明出处。
马燕龙个人博客:http://www.mayanlong.com
马燕龙个人微博:http://weibo.com/imayanlong 
马燕龙Github主页:https://github.com/yanlongma

iOS开发 - Swift使用JavaScriptCore与JS交互的更多相关文章

  1. 李洪强iOS经典面试题147-WebView与JS交互

    李洪强iOS经典面试题147-WebView与JS交互   WebView与JS交互 iOS中调用HTML 1. 加载网页 NSURL *url = [[NSBundle mainBundle] UR ...

  2. iOS开发Swift篇—(一)简单介绍

    iOS开发Swift篇—简单介绍 一.简介 Swift是苹果于2014年WWDC(苹果开发者大会)发布的全新编程语言 Swift在天朝译为“雨燕”,是它的LOGO 是一只燕子,跟Objective-C ...

  3. iOS开发Swift篇—(二)变量和常量

    iOS开发Swift篇—(二)变量和常量 一.语言的性能 (1)根据WWDC的展示 在进行复杂对象排序时Objective-C的性能是Python的2.8倍,Swift的性能是Python的3.9倍 ...

  4. iOS开发Swift篇—(三)字符串和数据类型

    iOS开发Swift篇—(三)字符串和数据类型 一.字符串 字符串是String类型的数据,用双引号""包住文字内容  let website = "http://www ...

  5. iOS开发Swift篇—(四)运算符

    iOS开发Swift篇—(四)运算符 一.运算符 1.Swift所支持的部分运算符有以下一些 赋值运算符:= 复合赋值运算符:+=.-= 算术运算符:+.-.*./ 求余运算符:% 自增.自减运算符: ...

  6. iOS开发Swift篇—(五)元组类型

    iOS开发Swift篇—(五)元组类型 一.元组类型介绍 1.什么是元组类型 元组类型由 N个 任意类型的数据组成(N >= 0),组成元组类型的数据可以称为“元素” 示例: let posit ...

  7. iOS开发Swift篇—(六)流程控制

    iOS开发Swift篇—(六)流程控制 一.swift中的流程控制 Swift支持的流程结构如下: 循环结构:for.for-in.while.do-while 选择结构:if.switch 注意:这 ...

  8. iOS开发Swift篇—(七)函数(1)

    iOS开发Swift篇—(七)函数 一.函数的定义 (1)函数的定义格式 func 函数名(形参列表) -> 返回值类型 { // 函数体... } (2)形参列表的格式 形参名1: 形参类型1 ...

  9. iOS开发Swift篇—(八)函数(2)

    iOS开发Swift篇—(八)函数(2) 一.函数类型 函数类型也是数据类型的一种,它由形参类型和返回值类型组成,格式是 (形参类型列表) -> 返回值类型 func sum(num1: Int ...

随机推荐

  1. H5 Bgsound

    Bgsound ■ 摘要 项目 说明 形式 <bgsound src="..."> 支持 e2+ 标签省略 开始标签:必须,结束标签:无 ■ 说明 bgsound 是 ...

  2. 使用awk截取某时间段的日志

    想要取出文件里面时间是9点到12点的数据,文件内容如下: 2012-09-05 01:48:47,150 WARN  [WorkManager(3)-72] [service.PhoneRangeMa ...

  3. SQL 中的常用函数及使用

    在SQL中我们使用的函数有很多,我们经常使用的就是下面的一些函数,那么我一一列举数来: 1:聚合函数:MAX 返回指定数据的最大值. MIN 返回指定数据的最小值. COUNT 返回指定组中项目的数量 ...

  4. Mybatis的@Options注解

    mybatis的@Options注解能够设置缓存时间,能够为对象生成自增的key 第一个使用场景: 有一个表 CREATE TABLE instance ( instance_id BIGINT UN ...

  5. servlet中的过滤器 国际化

    1. 过滤器 基本概念 过滤器是需要在xml中配置的. 为什么需用到过滤器? 项目开发中,经常会涉及到重复代码的实现! 注册 ----à Servlet [1. 设置编码] ----à  JSP 修改 ...

  6. Javascript:面试经典套路-查重(reduce)

    今天在偶然间查看到了一段代码,代码使用了很短的篇幅完成了字符串统计相同字符次数这个经典面试题,其中用到了reduce这个方法,网上查了查,没有查到什么有价值的东西,导致浪费了我一些时间才看懂,现将我的 ...

  7. 【一】Swift 3.0 新浪微博项目实战 -整体框架搭建

    最近要接手swift,所以找了个视频跟着做一下实战项目,在此记录一下过程和心得 框架搭建和目录拆分 关键词:MVVM 架构,桥接文件 桥接文件用于引入OC的头文件,Swift就可以正常使用(宏除外). ...

  8. AP付款出现(-1)例外处理

    ---手工处理方法---1.根据收款编号查询事件表中的"事件ID"---2.将AP_CHECKS_ALL表中的PAYMENT_TYPE_FLAG 标记由"Q"更 ...

  9. 微信web开发者工具使用

    1.首先启动微信web开发者工具, 2.启动之后,点击移动端调试, 3.选择普通调试,然后,将手机和电脑置于同一个网段之中,可以通过电脑发出一个wifi,让手机连入就行 4.如果,电脑室台式机的话,没 ...

  10. 收集下shell使用笔记

    让进程转入后台: Ctrl + z 将进程转到前台: fg 产生随机的十六进制数,其中n是字符数: openssl rand -hex n 截取前5个字符: ${variable::} 一次创建多个目 ...