文章目录
  1. 1. JS和OC相互调用
    1. 1.1. OC调用JS
    2. 1.2. JS调用OC
    3. 1.3. 第三方框架

JS和OC相互调用

OC调用JS

  • 通过OC调用HTML,主要通过webView执行stringByEvaluatingJavaScriptFromString:
  • 也可以 返回自己想要的值,这样就把JS中的数据出传递到OC中了
#import "ViewController.h"

@interface ViewController ()<UIWebViewDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *webView;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

//加载网页
NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
}

#pragma mark - 操作网页
-(void)webViewDidFinishLoad:(UIWebView *)webView{
// 删除
NSString *str1 = @"var word = document.getElementById('word');";
NSString *str2 = @"word.remove();";
// 执行JS脚本
[webView stringByEvaluatingJavaScriptFromString:str1];
[webView stringByEvaluatingJavaScriptFromString:str2];

// 更改
NSString *str3 = @"var change = document.getElementsByClassName('change')[0];"
"change.innerHTML = '好你的哦!';";
[webView stringByEvaluatingJavaScriptFromString:str3];

// 插入图片
NSString *str4 =@"var img = document.createElement('img');"
"img.src = 'img_01.jpg';"
"img.width = '160';"
"img.height = '80';"
"document.body.appendChild(img);";
[webView stringByEvaluatingJavaScriptFromString:str4];

}

JS调用OC

  • html中处理
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<button onclick="getImage();">访问相册</button>

<script>
function getImage(){
/*这里对这个函数定义一个协议头,在OC里进行解析,当点击这个按钮时,就会调用这个方法,然后这个事件会通过代理方法传递到OC中,在OC中再次响应点击的处理事件,打开相册*/
window.location.href = 'slq://getImage';
}
</script>
</body>
</html>
  • OC中处理
- (void)viewDidLoad {
[super viewDidLoad];
//加载网页
NSURL *url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];

}
/**
* 加载webView的任何请求都会经过这个方法,返回yes表示允许加载,NO表示禁止加载
*/
-(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
NSString *str = request.URL.absoluteString;
NSLog(@"%@", str);
NSRange range = [str rangeOfString:@"slq://"];
if (range.location != NSNotFound) {
// 截取字符串,获取方法名
NSString *method = [str substringFromIndex:range.location + range.length];
// 字符串转换成方法名
SEL sel = NSSelectorFromString(method);
[self performSelector:sel];
}
return YES;
}

// 访问相册
- (void)getImage{
UIImagePickerController *pickerImg = [[UIImagePickerController alloc]init];
pickerImg.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

[self presentViewController:pickerImg animated:YES completion:nil];
}

第三方框架

  • WebViewJavascriptBridge
  • 该框架的主要使用方法是在iOS端中先创建一个WebViewJavascriptBridge对象,并运用该对象实现交互.
  • 将框架导入工程后,包含头文件#import "WebViewJavascriptBridge.h"

  • 在js中实现如下方式实现

//<script>
window.onerror = function(err) {
log('window.onerror: ' + err)
}

function connectWebViewJavascriptBridge(callback) {
//注意,所有bridge函数都应写在这里面
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener('WebViewJavascriptBridgeReady', function() {
callback(WebViewJavascriptBridge)
}, false)
}
}
connectWebViewJavascriptBridge(function(bridge) {
var uniqueId = 1
function log(message, data) {
var log = document.getElementById('log')
var el = document.createElement('div')
el.className = 'logLine'
el.innerHTML = uniqueId++ + '. ' + message + ':<br/>' + JSON.stringify(data)
if (log.children.length) { log.insertBefore(el, log.children[0]) }
else { log.appendChild(el) }
}

// 注册js函数,可使用key在OC中直接调用
bridge.init(function(message, responseCallback) {
log('JS got a message', message)
var data = { 'Javascript Responds':'Wee!' }
log('JS responding with', data)
responseCallback(data)
})
// 注册js函数,可使用key在OC中直接调用
bridge.registerHandler('testJavascriptHandler', function(data, responseCallback) {
log('ObjC called testJavascriptHandler with', data)
var responseData = { 'Javascript Says':'Right back atcha!' }
log('JS responding with', responseData)
responseCallback(responseData)
})
// 注册js函数,可使用key在OC中直接调用
bridge.registerHandler('testCallback', function(data, responseCallback) {
log('test', data)
var responseData = { 'Javascript Says':'test' }
log('JS responding with', responseData)
responseCallback(responseData)
})
// 添加按钮
var button = document.getElementById('buttons').appendChild(document.createElement('button'))
button.innerHTML = 'Send message to ObjC'
button.onclick = function(e) {
e.preventDefault()
var data = 'Hello from JS button'
log('JS sending message', data)
bridge.send(data, function(responseData) {
log('JS got response', responseData)
})
}
// 添加按钮
var button1 = document.getElementById('buttons').appendChild(document.createElement('button'))
button1.innerHTML = 'button test'
button1.onclick = function(e) {
e.preventDefault()
var data = 'button test'
log('JS sending message', data)
// 调用OC中初始化方法(创建`bridge`)
bridge.send(data, function(responseData) {
log('JS got response', responseData)
})
}

document.body.appendChild(document.createElement('br'))

// 添加按钮
var callbackButton = document.getElementById('buttons').appendChild(document.createElement('button'))
callbackButton.innerHTML = 'Fire testObjcCallback'
callbackButton.onclick = function(e) {
e.preventDefault()
log('JS calling handler "testObjcCallback"')
// 调用OC中方法(`key`)
bridge.callHandler('testObjcCallback', {'foo': 'bar'}, function(response) {
log('JS got response', response)
})
}
})
// </script>
  • 在OC中可按如下操作
@property (nonatomic, strong) WebViewJavascriptBridge *bridge; // 声明属性

//
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];

if (_bridge) { return; }

UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:webView];
self.webView = webView;
[self loadExamplePage:self.webView];
// 开启日志信息输出
[WebViewJavascriptBridge enableLogging];

// 创建birdge对象
_bridge = [WebViewJavascriptBridge bridgeForWebView:webView handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"ObjC received message from JS: %@", data);
responseCallback(@"Response for message from ObjC");
UIViewController *vc = [[UIViewController alloc] init];
vc.view.backgroundColor = [UIColor redColor];
self.navigationController.hidesBarsOnTap = YES;
[self.navigationController pushViewController:vc animated:YES];
}];

// 注册OC中回调,可用于在JS中调用
[_bridge registerHandler:@"objcCallback" handler:^(id data, WVJBResponseCallback responseCallback) {
NSLog(@"objcCallback called: %@", data);
responseCallback(@"Response from objcCallback");
}];

// 调用JS中bridge.init的方法
[_bridge send:@"A string sent from ObjC before Webview has loaded." responseCallback:^(id responseData) {
NSLog(@"objc got response! %@", responseData);
}];

// 在OC中调用JS中方法
[_bridge callHandler:@"testJavascriptHandler" data:@{@"foo":@"before ready."} ];

// 在OC中调用JS中方法
[_bridge callHandler:@"testCallback" data:nil responseCallback:^(id responseData) {

}];
}

- (void)loadExamplePage:(UIWebView*)webView {
NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"ExampleApp" ofType:@"html"];
NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[webView loadHTMLString:appHtml baseURL:baseURL];
}
  • WebViewJavascriptBridge来实现OC和H5交互还是比较方便的,而且不必担心使用JavaDcriptCore可能导致的上线被拒。
文章目录
  1. 1. JS和OC相互调用
    1. 1.1. OC调用JS
    2. 1.2. JS调用OC
    3. 1.3. 第三方框架