UIWebview 相关
1.stringByEvaluatingJavaScriptFromString
使用上面 stringByEvaluatingJavaScriptFromString 来实现。前提要先用webview 加载当前界面。
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"intercept" ofType:@"html"]];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
1.oc 调用JS
[self.webView stringByEvaluatingJavaScriptFromString:@"showResponse('点击了原生的按钮11111111111')"];
js的方法怎么写呢?
/**
* 显示响应信息
* @param response 响应信心
*/
function showResponse(response) {
$('#response').text(response);
return response;
}
2.js调oc
js调oc这里其实就是打开一个新的链接或者通过打开新的界面的方式。下面是通过
window.location = 'app://login?account=13011112222&password=123456'; location来实现的,window location 和frame的方式都可以的。
oc这边只要拦截是否打开新的界面就可以获取的到。
#pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *scheme = request.URL.scheme;
NSString *host = request.URL.host;
// 一般用作交互的链接都会有一个固定的协议头,这里我们一“app”作为协议头为了,实际项目中可以修改
if ([scheme isEqualToString:@"app"]) { // scheme为“app”说明是做交互的链接
if ([host isEqualToString:@"login"]) { // host为“login”对应的就是登录操作
NSDictionary *paramsDict = [request.URL getURLParams];
NSString *account = paramsDict[@"account"];
NSString *password = paramsDict[@"password"];
NSString *msg = [NSString stringWithFormat:@"执行登录操作,账号为:%@,密码为:%@", account, password];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:msg delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
} else if ([host isEqualToString:@"share"]) { // host为“share”对应的就是分享操作
NSDictionary *paramsDict = [request.URL getURLParams];
NSString *title = [paramsDict[@"title"] stringByRemovingPercentEncoding];
NSString *desc = [paramsDict[@"desc"] stringByRemovingPercentEncoding];
NSString *msg = [NSString stringWithFormat:@"执行分享操作,title为:【%@】,desc为:【%@】", title, desc];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:msg delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
}
return NO;
}
return YES;
}
2.JSContext 方式
@property(nonatomic, strong) JSContext *jsContext;
// 加载测试用的HTML页面
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"jscontext" ofType:@"html"]];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
1.JS调用OC
[self.jsContext evaluateScript:@"showResponse('点击了按钮1111111111111111')"];
oc被调用的写法,其实这里和前一个的写法类似
/**
* 显示响应信息
* @param response 响应信心
*/
function showResponse(response) {
$('#response').text(response);
}
1.OC调用JS
下面是oc的写法
app.login("13011112222", "123456");
js 像上面调用,有两个问题,app是哪个对象,app这个对象的login方法是什么呢?
下面就是核心代码
//这种方式首先都要这样写
self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
context.exception = exception;
NSLog(@"异常信息:%@", exception);
};
//定义js文件中调用方法的对象是谁,这里定义了js 对象的里面的app对象就是JSContextModel
//app 调 app.login("13011112222", "123456");就是说在在调用 JSContextModel 的 login方法
self.jsContext[@"app"] = [[JSContextModel alloc] init];
下面就是在JSContextModel 对象里面定义的login 方法了。
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
@protocol JsContextExport<JSExport>
/**
* 登出方法,js调用的方法名也是logout
*/
- (void)logout;
/**
* 登录方法,JSExportAs的作用就是给OC方法导出一个js方法名,例如下面的方法js调用就是 login("your account", "your password")。在多参数的方法声明时必须使用这种方式
*/
JSExportAs(login, - (void)loginWithAccount:(NSString *)account password:(NSString *)password);
/**
* 获取登录信息
* @return 当前登录用户的身份信息。JSContext方式调用OC时,方法的返回值只能是NSString、NSArray、NSDictionary、NSNumber、BooL,其他类型不能解析
*/
- (NSDictionary *)getLoginUser;
@end
@interface JSContextModel : NSObject<JsContextExport>
@end
@implementation JSContextModel
- (void)logout {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:@"执行【登出】操作" delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
}];
}
- (void)loginWithAccount:(NSString *)account password:(NSString *)password {
NSString *msg = [NSString stringWithFormat:@"执行登录操作,账号为:%@,密码为:%@", account, password];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:msg delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
}];
}
- (NSDictionary *)getLoginUser {
return @{
@"user_id": @(666),
@"username": @"你就说6不6",
@"sex": @"未知",
@"isStudent": @(NO)
};
}
@end
JSExportAs的作用就是给OC方法导出一个js方法名,说白了就是起别名,在多个参数必须这个做。
WebViewJavascriptBridge方式
WebViewJavascriptBridge 是一个第三方框架。
WKWebView
evaluateJavaScript
这个方式其实和UIWebView的方式基本一致。
oc调用JS
// 加载测试用的HTML页面
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"intercept" ofType:@"html"]];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
调用完不需要回调的
[self.webView evaluateJavaScript:@"showResponse('点击了原生的按钮11111111111')" completionHandler:nil];
调用完需要回调的
[self.webView evaluateJavaScript:@"showResponse('点击了原生的按钮22222222222')" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"%@", error);
} else {
NSLog(@"%@", response);
}
}];
JS代码
/**
* 显示响应信息
* @param response 响应信心
*/
function showResponse(response) {
$('#response').text(response);
return response;
}
JS调用OC
和上面UIwebView的方式一致
window.location = 'app://login?account=13011112222&password=123456';
WKWebView 拦截请求
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
NSString *scheme = request.URL.scheme;
NSString *host = request.URL.host;
// 一般用作交互的链接都会有一个固定的协议头,这里我们一“app”作为协议头为了,实际项目中可以修改
if ([scheme isEqualToString:@"app"]) { // scheme为“app”说明是做交互的链接
if ([host isEqualToString:@"login"]) { // host为“login”对应的就是登录操作
NSDictionary *paramsDict = [request.URL getURLParams];
NSString *account = paramsDict[@"account"];
NSString *password = paramsDict[@"password"];
NSString *msg = [NSString stringWithFormat:@"执行登录操作,账号为:%@,密码为:%@", account, password];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:msg delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
} else if ([host isEqualToString:@"share"]) { // host为“share”对应的就是分享操作
NSDictionary *paramsDict = [request.URL getURLParams];
NSString *title = [paramsDict[@"title"] stringByRemovingPercentEncoding];
NSString *desc = [paramsDict[@"desc"] stringByRemovingPercentEncoding];
NSString *msg = [NSString stringWithFormat:@"执行分享操作,title为:【%@】,desc为:【%@】", title, desc];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:msg delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
}
// ... 这里可以继续加
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
webKit的方式
OC 调用JS
#define FUNC_LOGIN @"login"
#define FUNC_LOGOUT @"logout"
WKUserContentController *confVc = self.webView.configuration.userContentController;
[confVc addScriptMessageHandler:self name:FUNC_LOGIN];
[confVc addScriptMessageHandler:self name:FUNC_LOGOUT];
// 加载测试用的HTML页面
NSURL *url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"webkit" ofType:@"html"]];
[self.webView loadRequest:[NSURLRequest requestWithURL:url]];
真正的调用代码
[self.webView evaluateJavaScript:@"showResponse('点击了原生的按钮22222222222')" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
if (error) {
NSLog(@"%@", error);
} else {
NSLog(@"%@", response);
}
}];
下面是对应的JS代码
function showResponse(response) {
$('#response').text(response);
return '调用成功';
}
JS 调用OC
window.webkit.messageHandlers.login.postMessage({
'account': '13000000000',
'password': '123456'
});
oc那边类似于上面的拦截
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:FUNC_LOGIN]) {
if (![message.body isKindOfClass:[NSDictionary class]]) {
return;
}
NSDictionary *data = message.body;
NSString *account = data[@"account"];
NSString *password = data[@"password"];
NSString *msg = [NSString stringWithFormat:@"执行登录操作,账号为:%@,密码为:%@", account, password];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:msg delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
return;
}
if ([message.name isEqualToString:FUNC_LOGOUT]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"原生弹窗" message:@"执行登出操作" delegate:nil cancelButtonTitle:@"好" otherButtonTitles:nil, nil];
[alert show];
return;
}
}
WebViewJavascriptBridge方式
看前面webview的部分