本地HTML
简单的两个按钮演示OC
传数据到JavaScript
和OC
获取JavaScript
数据。
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function loadURL(url) {
var iFrame;
iFrame = document.createElement("iframe");
iFrame.setAttribute("src", url);
iFrame.setAttribute("style", "display:none;");
iFrame.setAttribute("height", "0px");
iFrame.setAttribute("width", "0px");
iFrame.setAttribute("frameborder", "0");
document.body.appendChild(iFrame);
// 发起请求后这个iFrame就没用了,所以把它从dom上移除掉
iFrame.parentNode.removeChild(iFrame);
iFrame = null;
}
function asyncAlert(content) {
setTimeout(function(){
alert(content);
},1);
}
function showAlert() {
loadURL("test://showAlert");
}
function alertWithMessage(content) {
asyncAlert(content);
document.getElementById("returnValue").value = content;
}
function setColor() {
loadURL("test://setColor?r=10&g=170&b=250&a=0.5");
}
</script>
</head>
<body>
<input type="button" value="OC调用JS方法" onclick="showAlert()">
<input type="button" value="JS传数据到OC" onclick="setColor()">
</body>
</html>
UIWebView拦截URL
加载WebView
- (void)loadWebView {
self.webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
self.webView.delegate = self; // 设置代理
NSURL *indexURL = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
NSURLRequest *request = [NSURLRequest requestWithURL:indexURL];
[self.webView loadRequest:request]; // 加载html
[self.view addSubview:self.webView];
}
拦截URL
WebView
拦截URL
是在shouldStartLoadWithRequest:
代理方法中拦截每一个链接的Request
,return YES
就会加载这个链接,return NO
就不会加载这个连接。
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *scheme = request.URL.scheme;
if ([scheme isEqualToString:@"test"]) {
[self handleURL:request.URL];
return NO;
}
return YES;
}
这里通过scheme
,来拦截掉自定义的URL
就非常容易了,如果不同的方法使用不同的scheme
,那么判断起来就非常的麻烦。
- (void)handleURL:(NSURL *)URL {
if ([URL.host isEqualToString:@"showAlert"]) {
// 将结果返回给JS
NSString *jsStr = [NSString stringWithFormat:@"alertWithMessage('%@')",@"OC调用JS的方法"];
[self.webView stringByEvaluatingJavaScriptFromString:jsStr];
}
else if ([URL.host isEqualToString:@"setColor"]) {
// 解析传过来的字符串,拿到属于颜色的部分
NSArray *params =[URL.query componentsSeparatedByString:@"&"];
NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
for (NSString *paramStr in params) {
NSArray *dicArray = [paramStr componentsSeparatedByString:@"="];
if (dicArray.count > 1) {
NSString *decodeValue = [dicArray[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[tempDic setObject:decodeValue forKey:dicArray[0]];
}
}
CGFloat r = [[tempDic objectForKey:@"r"] floatValue];
CGFloat g = [[tempDic objectForKey:@"g"] floatValue];
CGFloat b = [[tempDic objectForKey:@"b"] floatValue];
CGFloat a = [[tempDic objectForKey:@"a"] floatValue];
// 设置导航颜色方便观察
self.navigationController.navigationBar.backgroundColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a];
}
}
UIWebView调用JS方法
// UIWebView调用JS方法
- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;
如果回调执行的JS
方法带参数,而参数不是字符串时,不要加单引号,否则可能导致调用JS
方法失败。
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userProfile options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonStr = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *jsStr = [NSString stringWithFormat:@"loginResult('%@',%@)",type, jsonStr];
[self.webView stringByEvaluatingJavaScriptFromString:jsStr];
往HMTL
的JS
环境中插入全局变量、JS
方法等。
[webView stringByEvaluatingJavaScriptFromString:@"var arr = [3, 4, 'abc'];"];
效果:
WKWebView拦截URL
WKWebView
与UIWebView
拦截URL
的处理方式基本一样。除了代理方法和WKWebView
的使用不太一样。
加载WKWebView
- (void)loadWKWebView {
WKWebViewConfiguration *config = [WKWebViewConfiguration new];
WKPreferences *preferences = [WKPreferences new];
preferences.minimumFontSize = 30;
config.preferences = preferences;
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
self.webView.UIDelegate = self;
self.webView.navigationDelegate = self;
NSURL *URL = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"html"];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
[self.webView loadRequest:request];
[self.view addSubview:self.webView];
}
拦截URL
使用WKNavigationDelegate
中的代理方法,拦截自定义的URL
来实现JS
调用OC
方法。注意调用decisionHandler
这个block
,否则会导致App
崩溃。
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSString *scheme = navigationAction.request.URL.scheme;
if ([scheme isEqualToString:@"test"]) {
[self handleURL:navigationAction.request.URL];
decisionHandler(WKNavigationActionPolicyCancel); //不允许跳转
return;
}
decisionHandler(WKNavigationActionPolicyAllow); // 允许跳转
}
- (void)handleURL:(NSURL *)URL {
if ([URL.host isEqualToString:@"showAlert"]) {
NSString *jsStr = [NSString stringWithFormat:@"alertWithMessage('%@')",@"OC调用JS的方法"];
[self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
NSLog(@"%@----%@",result, error);
}];
}
else if ([URL.host isEqualToString:@"setColor"]) {
NSArray *params =[URL.query componentsSeparatedByString:@"&"];
NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
for (NSString *paramStr in params) {
NSArray *dicArray = [paramStr componentsSeparatedByString:@"="];
if (dicArray.count > 1) {
NSString *decodeValue = [dicArray[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[tempDic setObject:decodeValue forKey:dicArray[0]];
}
}
CGFloat r = [[tempDic objectForKey:@"r"] floatValue];
CGFloat g = [[tempDic objectForKey:@"g"] floatValue];
CGFloat b = [[tempDic objectForKey:@"b"] floatValue];
CGFloat a = [[tempDic objectForKey:@"a"] floatValue];
self.navigationController.navigationBar.backgroundColor = [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:a];
}
}
WKWebView调用JS方法
JS
执行成功还是失败会在completionHandler
中返回。所以使用这个API
就可以避免执行耗时的JS
,或者alert
导致界面卡住的问题。
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
WKWebView中使用弹窗
如果在WKWebView
中使用alert
、confirm
等弹窗,就得实现WKUIDelegate
中相应的代理方法。
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
UIAlertController *alertCrontroller = [UIAlertController alertControllerWithTitle:@"提示" message:message preferredStyle:UIAlertControllerStyleAlert];
[alertCrontroller addAction:[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
completionHandler();
}]];
[self presentViewController:alertCrontroller animated:YES completion:nil];
}
其中completionHandler
这个block
一定得调用,至于在哪里调用,倒是无所谓,我们也可以写在方法实现的第一行,或者最后一行。
网友评论