<一>iOS与H5交互
在iOS控制器中加载UIWebView,设置代理,遵守UIWebViewDelegate协议。
一、iOS调用JS方法
通过iOS调用JS代码实现起来比较方便直接调用UIWebView的方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
(下面加粗字符串代码 里面的字符串 表示的是html中创建删除更改标签的代码)
1.查询标签
NSString *str = @"var word = document.getElementById('word');" @"alert(word.innerHTML)";
[webView stringByEvaluatingJavaScriptFromString:str];
2.为网页添加标签:
NSString *str = @"var img = document.createElement('img');" "img.src = 'icon5.jpg';" "img.width = 300;""img.heigth = 100;""document.body.appendChild(img);";
[webView stringByEvaluatingJavaScriptFromString:str];
3.删除网页标签:
NSString *str1 = @"var word = document.getElementById('word');" @"word.remove();";
[webView stringByEvaluatingJavaScriptFromString:str1];
4.更改标签:
NSString *str2 = @"var change = document.getElementsByClassName('change')[0];" "change.innerHTML = 'hello';";
NSString *result = [webView stringByEvaluatingJavaScriptFromString:str2];
HTML端代码:
HTML端代码:访问相册//js方法
function getImage(){
window.location.href = "wxd://getImage";
}
二、JS调用iOS方法:
1.第一种方法比较简单,通过字符串的比对。这种方式iOS端代码比较简单,网页加载完成后后台需要重新定义网页url,将移动端需要的参数拼接到url上返回,或者按照和后台约定好的字段来进行字符串比对以达到调用iOS方法的目的。下面贴代码。
oc代码:(需要实现webView的协议)
// 拦截协议头,调取系统摄像头 #pragma mark UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType: (UIWebViewNavigationType)navigationType {
NSString *str = request.URL.absoluteString;
if ([str containsString:@"wxd://"]) {
[self getImage]; //此处解析上面js调用相册是的href 的字符串
}
return YES;
}
- (void)getImage {
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
//调用相册
//实例化控制器
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
// 是否有图片选取框
picker.allowsEditing = YES;
[self presentViewController:picker animated:YES completion:nil];
}
}
<二>第二种方法,
JS直接用oc方法名来调用oc方法,类似于安卓.addJavascriptInterface(new JsObject(), "Android")方法,头文件需要导入#import。
首先创建一个继承自NSObject的类,在这里我命名为va,.h代码如下:
.m中实现协议方法,代码如下:
之后在加载webView的控制器中调用:
到此为止,oc代码就已经写完了,我们只需告诉JS端使用testobject类,就可以调oc的方法了。下面附上JS调用的代码:
webView中JSContext的获取使用 javascriptcore交互的核心是通过从webview中获取到当前的JSContext,在JSContext中执行对应的操作,一般情况下可以通过以下接口获取到当前页面的JSContext_defaultContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
如果webview中进行了不同的页面切换,就需要在每次完成新的页面加载后,刷新当前记录的JSContext,确保JSContext实时有效。
-(void)webViewDidFinishLoad:(UIWebView *)webView { //网页加载完成调用此方法 _defaultContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
}
.Objective-C调用javeScript这部分比较简单,第一种方案可以直接使用
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
调用javeScript提供的接口,传参。
//假设JS中提供login函数
[webView stringByEvaluatingJavaScriptFromString:@"login('username','password')"];
第二种方案,使用JSContext获取对应的接口后,使用
- (JSValue *)callWithArguments:(NSArray *)arguments;
或 - (JSValue )evaluateScript:(NSString )script;
[_defaultContext evaluateScript:@"login('username','password')"];
//通过 JSContext 调用JS 方法,执行 JSValue *JSfunc =_defaultContext[@"login"];
[JSfunc callWithArguments:@[@'username',@'password']];
.javeScript调用Objective-C这个需要使用javascriptcore提供的JSExport,在Objective-C中实现该protocol的方法,就可以在javeScript使用到的接口了。
JSExport相当于跨语言提供的protocol。
#include// Protocol to list bindings@protocol JSBridgeExport
//为webview中提供与native一致的提示功能
- (void)showTip:(NSString *)tip;
@end
@interface JSBridge : NSObject
@end
@implementation JSBridge
- (void)showTip:(NSString *)tip{
[TopWindow makeToast:tip];
}
@end
首先将在当前JSContext进行类注册_defaultContext[@"jsbridge"] = [[JSBridge alloc]init];,然后就可以在JS中通过jsbridge调用OC提供的方法接口了。
[_defaultContext evaluateScript:@"jsbridge.showTip(\"this is a tip from webview\")"];
存在的问题
正如第一步中刷新JSContext一样,在不同页面进行刷新后的时候,都需要将OC提供给JS的方法进行注册,确保当前JS环境中提供的接口有效。
-(void)webViewDidFinishLoad:(UIWebView *)webView {
//网页加载完成调用此方法
//刷新当前记录JSContext,刷新接口
_defaultContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
_defaultContext[@"jsbridge"] = [[JSBridge alloc]init];
}