UIWebView实现OC调用JS有两种方式
1、stringByEvaluatingJavaScriptFromString
2、JavaScriptCore
JS调用OC也有两种方式
1、request的url拦截
2、JavaScriptCore
其实从这里就可以看出JavaScriptCore很棒。
先写html
使用url拦截的方式需要提前定义好url的规则,这里的简单的定义个规则lfjstooc:///methodName/para1/para2
(规则可以是各种各样的,只要你能拦截下来就行),先看一下我们预先写好的html文件
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<title>UIWebView中OC与JS交互</title>
</head>
<style type="text/css">
.button {
background: #f5be14;
margin: 10px;
text-align: center;
width: 300px;
height: 44px;
line-height: 44px;
margin: 10px auto;
border-radius: 5px;
}
#setImage {
width: 200px;
height: 200px;
margin: 0 auto;
}
</style>
<body>
<div class="button" onclick="firstClick()">今晚打老虎</div>
<div class="button" onclick="secondClick()">请用力的点我</div>
<div class="button" onclick="thirdClick()">弹我弹我</div>
<div class="button" onclick="forthClick()">选择图片</div>
<div id="setImage"></div>
</body>
<script type="text/javascript">
var prefixStandard = "LFJSToOC://";
function getText(index) {
return document.getElementsByClassName("button")[0].innerText;
}
function firstClick() {
var action = "firstClick";
var token = getText(0);
setUrl(action, token);
}
function secondClick() {
var action = "secondClick";
var token = getText(1);
setUrl(action, token);
}
function thirdClick() {
var action = "thirdClick";
var token = getText(2);
setUrl(action, token);
}
function forthClick() {
var action = "forthClick";
var token = getText(3);
setUrl(action, token);
}
function setUrl(action, token) {
var url = prefixStandard + "/" + action + "/" + token;
loadUrl(url);
}
function loadUrl(url) {
window.location.href = url;
}
function showImageOnDiv(imageStr) {
var imgDiv = document.getElementById("setImage");
imgDiv.innerHTML = "<image style='width:200px;' src='data:image/png;base64,"+imageStr+"'>";
}
</script>
</html>
这里实现的效果是这样的
HTML的效果
我们想要做的是,点击不同的按钮,在源生弹窗显示按钮上的字。
UIWebView
1、UIWebView初始化
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-HOME_INDICATOR_HEIGHT)];
self.webView.delegate = self;
self.webView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.webView];
//这里在加载本地的html文件
NSURL *url = [[NSBundle mainBundle] URLForResource:@"UIWebView.html" withExtension:nil];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
[self.webView loadRequest:request];
2、实现代理
UIWebView的主要四个代理如下,
//加载所有webview的请求数据,以及控制是否要加载,所以JS调用的拦截在这里实现。
/*
JS的UIWebViewNavigationType对应如下样式,可以根据业务需求更细致的判断。
typedef NS_ENUM(NSInteger, UIWebViewNavigationType) {
UIWebViewNavigationTypeLinkClicked, 点击
UIWebViewNavigationTypeFormSubmitted, 提交
UIWebViewNavigationTypeBackForward, 返回
UIWebViewNavigationTypeReload, 刷新
UIWebViewNavigationTypeFormResubmitted, 重复提交
UIWebViewNavigationTypeOther 其他
} API_UNAVAILABLE(tvos);
*/
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
//开始加载
- (void)webViewDidStartLoad:(UIWebView *)webView API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
//加载完成
- (void)webViewDidFinishLoad:(UIWebView *)webView API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
//加载失败
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error API_DEPRECATED("No longer supported.", ios(2.0, 12.0));
JS调OC
这里我们先用普通的方式"request拦截",我们都知道webView在调用一个Url之前会走- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
这个代理,我们看到有NSURLRequest这个类型的参数,而从这个request中可以获取到JS调用的url(lfjstooc:///methodName/para1/para2
),于是我们的故事开始了。
1、request.URL.scheme
我们通过scheme路由发放响应
if ([request.URL.scheme.lowercaseString isEqualToString:@"lfjstooc"]) {
return NO;//webview停止继续加载
}
2、request.URL.pathComponents
通过pathComponents获取函数名和参数
NSArray *arr = request.URL.pathComponents;
/*
(
"/",
secondClick,//方法名
"this is the message"//一个NSString类型参数
)
*/
3、调用OC方法
当然调用OC方法可以有很多种,[self methodName]
直接调也行,performSelector: withObject:
这种方式也行,我这里用objc_msgSend
objc_msgSend(self, sel, arr[2]);
综上,我们- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
里面代码如下
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
//拦截JS的回调
if ([request.URL.scheme.lowercaseString isEqualToString:@"lfjstooc"]) {
NSArray *arr = request.URL.pathComponents;
SEL sel = NULL;
if (arr.count > 2) {//表示调用js调用的方法有参数
sel = NSSelectorFromString([NSString stringWithFormat:@"%@:",arr[1]]);
} else if(arr.count == 2) {//js调用OC,数组中至少得有两个元素
sel = NSSelectorFromString(arr[1]);
}
objc_msgSend(self, sel, arr[2]);//调用对应的OC方法
return NO;
}
return YES;
}
OC调JS
OC调JS我们选择用UIWebView的stringByEvaluatingJavaScriptFromString
方法,比如调用js的docoument.title方法获取当前页面的标题。
NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
self.title = title;
下面举一个点击html页面的按钮调用源生的系统相册选择图片,并把图片放到html页面的例子,代码如下
首先响应JS调用的源生相册
//第四个按钮点击事件,调用系统相册
- (void)forthClick:(NSString *)str {
if (!self.imagePicker) {
self.imagePicker = [[UIImagePickerController alloc] init];
}
self.imagePicker.delegate = self;
self.imagePicker.allowsEditing = YES;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:self.imagePicker animated:YES completion:nil];
}
其次实现照片选择完毕的系统代理- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
#pragma mark -- UIImagePickerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
NSLog(@"info---%@",info);
UIImage *resultImage = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
NSData *imgData = UIImageJPEGRepresentation(resultImage, 0.01);
NSString *encodedImageStr = [imgData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
[self dismissViewControllerAnimated:YES completion:nil];
NSString *imageString = [self clearImageString:encodedImageStr];
NSString *jsFunctStr = [NSString stringWithFormat:@"showImageOnDiv('%@')",imageString];
//OC调用JS
[self.webView stringByEvaluatingJavaScriptFromString:jsFunctStr];
}
//清除base64串里面的东西
- (NSString *)clearImageString:(NSString *)str {
NSString *temp = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
temp = [temp stringByReplacingOccurrencesOfString:@"\r" withString:@""];
temp = [temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
return temp;
}
效果如下:
JS与OC交互-选择系统相册.gif
OK,以上就是UIWebView中OC与JS交互的内容,这种是比较简单的OC与JS交互,针对简单的业务使用起来很方便。
网友评论