native html5 ios,JSBridge——Web与Native交互之iOS篇

一、原理篇

在讲解原理之前,首先需要了解下iOS提供的UIWebView组件,苹果官方是这么介绍UIWebView组件的:

You can use the UIWebView class to embed web content in your application. To do so, you simply create a UIWebView object, attach it to a window, and send it a request to load web content. You can also use this class to move back and forward in the history of webpages, and you can even set some web content properties programmatically.

UIWebView是iOS内置的浏览器控件,UIWebView用于在APP中嵌入网页,通常是html网页,也可以是PDF、txt文档等。但需要注意的是,Safari浏览器使用的浏览器控件和UIwebView组件并不是同一个,两者在性能上有很大的差距。幸运的是,苹果发布iOS8的时候,新增了一个WKWebView组件,如果你的APP只考虑支持iOS8及以上版本,那么你就可以使用这个新的浏览器控件了。

关于UIWebView类,你需要知道的一些属性和方法

属性:

loading:是否处于加载中

canGoBack:A Boolean value indicating whether the receiver can move backward. (只读)

canGoForward:A Boolean value indicating whether the receiver can move forward. (只读)

request:The URL request identifying the location of the content to load. (read-only)

方法:

loadData:Sets the main page contents, MIME type, content encoding, and base URL.

loadRequest:加载网络内容

loadHTMLString:加载本地HTML文件

stopLoading:停止加载

goBack:后退

goForward:前进

reload:重新加载

stringByEvaluatingJavaScriptFromString:执行一段js脚本,并且返回执行结果

1.1 Native(Objective-C或Swift)调用Javascript方法

Native调用Javascript语言,是通过UIWebView组件的stringByEvaluatingJavaScriptFromString方法来实现的,该方法返回js脚本的执行结果。

// Swift

webview.stringByEvaluatingJavaScriptFromString("Math.random()")

// OC

[webView stringByEvaluatingJavaScriptFromString:@"Math.random();"];

1.2 Javascript调用Native(Objective-C或Swift)方法

反过来,Javascript调用Native,并没有现成的API可以直接拿来用,而是需要间接地通过一些方法来实现。UIWebView有个特性:在UIWebView内发起的所有网络请求,都可以通过delegate函数在Native层得到通知。这样,我们就可以在UIWebView内发起一个自定义的网络请求,通常是这样的格式:jsbridge://methodName?param1=value1&param2=value2

于是在UIWebView的delegate函数中,我们只要发现是jsbridge://开头的地址,就不进行内容的加载,转而执行相应的调用逻辑。

首先通过iframe发起一个网络请求,这个请求的作用是唤起Native APP的分享组件,将网页分享到朋友圈或分享给其他好友。JS端的核心代码如下所示:

var url = 'jsbridge://doAction?title=分享标题&desc=分享描述&link=http%3A%2F%2Fwww.baidu.com';

var iframe = document.createElement('iframe');

iframe.style.width = '1px';

iframe.style.height = '1px';

iframe.style.display = 'none';

iframe.src = url;

document.body.appendChild(iframe);

setTimeout(function() {

iframe.remove();

}, 100);

然后Webview就可以拦截这个请求,并且解析出相应的方法和参数。如下代码所示:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {

print("shouldStartLoadWithRequest")

let url = request.URL

let scheme = url?.scheme

let method = url?.host

let query = url?.query

if url != nil && scheme == "jsbridge" {

print("scheme == \(scheme)")

print("method == \(method)")

print("query == \(query)")

switch method! {

case "getData":

self.getData()

case "putData":

self.putData()

case "gotoWebview":

self.gotoWebview()

case "gotoNative":

self.gotoNative()

case "doAction":

self.doAction()

case "configNative":

self.configNative()

default:

print("default")

}

return false

} else {

return true

}

}

二、库的封装

在项目的实践中,我们逐渐抽象出一些通用的方法,这些方法基本上都是可以满足项目的需求。如下所示:

1.getData(datatype, callback, extra) H5从Native APP获取数据

使用场景:H5需要从Native APP获取某些数据的时候,可以调用这个方法。

参数

类型

是否必须

示例值

说明

datatype

String

userInfo

数据类型

callback

Function

回调函数

extra

Object

传递给Native APP的数据对象

示例代码:

JSBridge.getData('userInfo',function(data) {

console.log(data);

});

2.putData(datatype, data) H5告诉Native APP一些数据

使用场景:H5告诉Native APP一些数据,可以调用这个方法。

参数

类型

是否必须

示例值

说明

datatype

String

userInfo

数据类型

data

Object

{ username: 'zhangsan', age: 20 }

传递给Native APP的数据对象

示例代码:

JSBridge.putData('userInfo', {

username: 'zhangsan',

age: 20

});

3.gotoWebview(url, page, data) Native APP新开一个Webview窗口,并打开相应网页

参数

类型

是否必须

示例值

说明

url

String

网页链接地址,一般都只要传递URL参数就可以了

page

String

web

网页page类型,默认为web

data

Object

额外参数对象

示例代码:

// 示例1:打开一个网页

JSBridge.gotoWebview('http://www.youzan.com');

// 示例2:打开一个网页,并且传递额外的参数给Native APP

JSBridge.gotoWebview('http://www.youzan.com', 'goodsDetail', {

goods_id: 10000,

title: '这是商品的标题',

desc: '这是商品的描述'

});

4.gotoNative(page, data) 从H5页面跳转到Native APP的某个原生界面

参数

类型

是否必须

示例值

说明

page

String

loginPage

Native页面标示符,例如loginPage

data

Object

{ username: 'zhangsan', age: 20 }

额外参数对象

示例代码:

// 示例1:打开Native APP登录页面

JSBridge.gotoNative('loginPage');

// 示例2:打开Native APP登录页面,并且传递用户名给Native APP

JSBridge.gotoNative('loginPage', {

username: '张三'

});

5.doAction(action, data) 功能上的一些操作

参数

类型

是否必须

示例值

说明

action

String

copy

操作功能类型,例如分享、复制

data

Object

{ content: '这是要复制的内容' }

额外参数

示例代码:

// 示例1:调用Native APP复制一段文本到剪切板

JSBridge.doAction('copy', {

content: '这是要复制的内容'

});

// 示例2:调用Native APP的分享组件,分享当前网页到微信

JSBridge.doAction('share', {

title: '分享标题',

desc: '分享描述',

link: 'http://www.youzan.com',

imgs_url: 'http://wap.koudaitong.com/v2/common/url/create?type=homepage&index%2Findex=&kdt_id=63077&alias=63077'

});

三、调试篇

2.1 使用Safari进行UIWebView的调试

(1)首先需要打开Safari的调试模式,在Safari的菜单中,选择“Safari”→“Preference”→“Advanced”,勾选上“Show Develop menu in menu bar”选项,如下图所示。

9fd80b785de1

2-1

(2)打开真机或iPhone模拟器的调试模式,在真机或iPhone模拟器中打开设置界面,选择“Safari”→“高级”→“Web检查器”,选择开启即可,如下图所示。

9fd80b785de1

2-2

(3)将真机通过USB连上电脑,或者开启模拟器,Safari的“Develop”菜单下便会多出相应的菜单项,如图所示。

9fd80b785de1

Paste_Image.png

(4)Safari连接上UIWebView之后,我们就可以直接在Safari中直接修改HTML、CSS,以及调试Javascript。

9fd80b785de1

Paste_Image.png

四、一些坑

1、通过修改window.location.href也可以达到发起网络请求的效果,但是有一个很严重的问题,就是如果我们连续多次修改window.location.href的值,在Native层只能接收到最后一次请求,前面的请求都会被忽略掉。所以JS端发起网络请求的时候,需要使用iframe,这样就可以避免这个问题。

五、参考链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值