UIWebView(苹果已经弃用,长传ipa时会禁止,改用)
- UIWebView使用的基本步骤:
- 初始化UIWebView
//web文件可以是本地也可以是网址,区别只是请求地址不同,交互都一样
NSUrl *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@", self.webUrlStr]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:request];
self.webView.delegate = self;
- 遵守UIWebViewDelegate协议
- 读取UIWebView的内容
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//获取JS代码的执行环境/上下文/作用域
self.context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];//固定的
// 以 JSExport 协议关联 native 的方法
self.context[@"native"] = self;
//打印异常,由于JS的异常信息是不会在OC中被直接打印的,所以我们在这里添加打印异常信息,
self.context.exceptionHandler = ^(JSContext *context, JSValue *exception) {
context.exception = exception;
};
- 导入框架<JavaScriptCore/JavaScriptCore.h>
- 自定义协议,自定义的协议遵守< JSExport >协议
- 自定义协议里面写原生与JS交互的方法名
//原生调用web
JSExportAs(sendRequest, - (void)sendRequest:(NSString *)code);
JSExportAs(sendData, - (void)send:(NSString *)type WithDataParameter:(BOOL)args);
//其中JSExportAs是一个宏定义,用一个自定义的方法名代替js里面的方法名,比如原生里面调用-(void)sendRequest:(NSString *)code)这个方法就是间接调用了js里的window.TellNative.sendRequest(code)方法
#define sendRequest(code) window.TellNative.sendRequest(code)
#define sendData(type, args) window.TellNative.sendData(type, args)
//web调用原生
- (void)finishBlockly;
- (void)ShakeDetector;
- (void)SensorDetector;
- 原生向js里面传递参数,比如在- (void)sendRequest:(NSString *)code这个方法里面调用
- (void)sendRequest:(NSString *)code {
JSValue *jsParam = self.context[@“callback4DataStore”];//web里面的方法名callback4DataStore
NSLog(@"-------%@", jsParam);
NSString *str1 = @“query”;
NSString *str2 = @“1”;
NSString *str3 = @“0”;
//给web传的参数,没有传nil
[jsParam callWithArguments:@[str1,str2,str3]];
[jsParam callWithArguments:@[str1,str3]];
//还可以通过JSContext的evaluateScript方法传递
[self.context evaluateScript:[NSString stringWithFormat:@"约定的方法名(@"native")('参数1', '参数2')"]];
//另一种方式
NSString *jsString = [NSString stringWithFormat:@"约定的方法名(@"native")('参数1', '参数2')"];
[self.webView stringByEvaluatingJavaScriptFromString:jsString];
//UIWebView的-stringByEvaluatingJavaScriptFromString:方法可以执行JS代码。但只有在整个webView加载完成之后调用此方法才会有响应
}
- 总结
1、UIWebView协议拦截方式
- JS调用iOS
#pragma mark - UIWebViewDelegate
//! UIWebView在每次加载请求前会调用此方法来确认是否加载此请求
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
if ([request.URL.scheme caseInsensitiveCompare:@"native"] == NSOrderedSame) {
return NO;
}
return YES;
}
- 用safari浏览器调试web
首先打开模拟器或者真机设置中"Safari浏览器"→"高级"→"Web检查器"的开关
打开Safari浏览器—>打开系统偏好设置—>“高级”—>勾选"在菜单栏中显示"开发"菜单".
真机连接上数据线.或者开启模拟器就能在菜单栏"开发"选项中找到我们的设备或者是模拟器。
进入对应的WebView页面即可进行调试
WKWebView
WKScriptMessageHandler协议方式
- JS调用iOS
1、 导入WebKit框架头文件:#import <WebKit/WebKit.h>
2、遵守WKScriptMessageHandler协议
3、 //! 为userContentController添加ScriptMessageHandler,并指明name
WKUserContentController *userContentController = [[WKUserContentController alloc] init];
[userContentController addScriptMessageHandler:self name:@"jsToOc"];
4、//! 使用添加了ScriptMessageHandler的userContentController配置configuration
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
configuration.userContentController = userContentController;
5、 //! 使用configuration对象初始化webView
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
6、接收消息时的代理
//! WKWebView收到ScriptMessage时回调此方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name caseInsensitiveCompare:@"jsToOc"] == NSOrderedSame) {
}
}
PS:[userContentController addScriptMessageHandler:self name:@“jsToOc”]会引起循环引用问题。一般来说,在合适的时机removeScriptMessageHandler可以解决此问题。比如:在-viewWillAppear:方法中执行add操作,在-viewWillDisappear:方法中执行remove操作。
- iOS调用JS
evaluateJavaScript:completionHandler:方法来实现