在H5页面调用oc方法
背景---
假设公司有一个比较复杂的页面需要我们来做,但是呢,如果使用原生来做呢,布局复杂做出来的东西也不好(也就是出力不讨好),那么我们就可以和我们的前端(爸爸~~)商量一下,让其帮忙做这个页面,然后点击页面的一些控件(按钮或者其他),我们自己做跳转到原生界面或者怎么样,这个过程呢,就是ios与原生的交互。
今天只有一个例子,那就是如果在H5页面调用原生(iOS)的方法。通俗的说,就是页面人家前端给咱们做了,页面的点击事件或其他需要我们自己处理,我们怎么做~~~(部分代码参考一些前辈,如侵权请告知 删掉)
首先,我对交互这块真的不懂,仅仅是把我自己学的分享一下,抛砖引玉。
其次,建议用WKWebView,优势貌似比UIWebView多很多(google),而且今天在写代码发现UIWebView将要被废弃了,小伙伴们请周知~~(写的看着很多,其实就一点点内容)
先看一部分代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>html5page-oc</title>
<script>
function btn1Click() {
window.webkit.messageHandlers.NativeModel.postMessage({name: 'leeSin', age: 12});
alert("after call");
}
</script>
</head>
<body>
<input type="button" value="button c" onclick="btn1Click()">
</body>
</html>
小伙伴看到上面的这些第一感觉是啥?WTF?我是这么感觉得...,没办法还是得硬着头皮看啊 心累------
但我们仔细看看 里面有一个 function 这个和swift里面的func 有点类似,其实就是一个函数,这个函数名为btn1Click 有两个参数name age,另外看这句<input type="button" value="button c" onclick="btn1Click()"> 也就是这个是按钮的点击方法。知道了这个,我们就大体知道应该在我们的OC代码怎么处理这个点击方法了
-(WKWebView *)webView
{
if (!_webView) {
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
config.userContentController = [[WKUserContentController alloc]init];
[config.userContentController addScriptMessageHandler:self name:@"NativeModel"];
_webView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:config];
_webView.navigationDelegate = self;
}
return _webView;
}
上面是我们懒加载wkwebview的代码,这里的WKWebViewConfiguration 的文档说明:Using the WKWebViewConfiguration class, you can determine how soon a webpage is rendered, how media playback is handled, the granularity of items that the user can select, and many other options.
WKWebViewConfiguration is only used when a web view is first initialized. You cannot use this class to change the web view's configuration after it has been created.
也就是我们可以通过WKWebViewConfiguration配置网页的一些设置,比如网页的呈现时间,媒体播放的处理方式,用户可以选择的项目的粒度以及许多其他选项
WKUserContentController 的说明: A WKUserContentController object provides a way for JavaScript to post messages and inject user scripts to a web view.
翻译一下就是WKUserContentController对象为JavaScript提供了一种发布消息并将用户脚本注入Web视图的方法。
通过设置 WKWebViewConfiguration 的 addScriptMessageHandler:name 来设置JS事件的接收处理器,这边设置为当前对象self,这里的name需要设置为JS中的调用的Model:NativeModel 。(这个NativeModel一定要和前段提供给我们的一致!!这个NativeModel一定要和前段提供给我们的一致!!这个NativeModel一定要和前段提供给我们的一致!!)
/*! @abstract Adds a script message handler.
@param scriptMessageHandler The message handler to add.
@param name The name of the message handler.
@discussion Adding a scriptMessageHandler adds a function
window.webkit.messageHandlers.<name>.postMessage(<messageBody>) for all
frames.
*/
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
然后我们就可以在代理方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message 处理啦~~~
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
// do what u want to do
id body = message.body;
NSLog(@"=====%@",body);
}
下面是文章的全部代码
#import "ViewController.h"
#import <JavaScriptCore/JavaScriptCore.h>
#import <WebKit/WebKit.h>
@interface ViewController ()<WKScriptMessageHandler,WKNavigationDelegate>
@property (nonatomic,strong)WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [[NSBundle mainBundle]URLForResource:@"jsDemo" withExtension:@"html"];
NSURLRequest *requst = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requst];
[self.view addSubview:self.webView];
}
-(WKWebView *)webView
{
if (!_webView) {
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc]init];
config.userContentController = [[WKUserContentController alloc]init];
[config.userContentController addScriptMessageHandler:self name:@"NativeModel"];
_webView = [[WKWebView alloc]initWithFrame:self.view.frame configuration:config];
_webView.navigationDelegate = self;
}
return _webView;
}
#pragma marks -- delegate
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
id body = message.body;
NSLog(@"=====%@",body);
}
@end
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
// 因此这里要记得移除handlers
[self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"NativeModel"];
}
最后一定要把h5代码放到工程里呀 Command+N ---> Other-->Empty 赋值h5代码后 保存为XX.html 就ok啦
总结起来就三点内容:
1.前端和苹果移动端的方法名必须一致,且前端要以固定的格式来写方法,否则移动端收不到事件反馈;
2.通过 WKUserContentController 添加html中预留的方法;
3.实现 WKScriptMessageHandler 的代理方法;