UIWebView的效率比较低一些,在IOS9以下还是需要使用的,WKwebView在iOS9上运行良好,但是我们这里需要关注的是于JS的交互,本文探讨的是OC与JS参数相互传递,以及使用cookie这样一个折中的交互。
import <objc/runtime.h>
import <MobileCoreServices/MobileCoreServices.h>
import <JavaScriptCore/JavaScriptCore.h>
import "WebViewJavascriptBridge.h"
import "NSObject+ViewControlTool.h"
import <WebKit/WebKit.h>
@protocol JSWebViewControllerExprot <JSExport> //该地方就是为UIWEBView 的oc响应代码
- (void)postMvc:(NSString * _Nonnull)jsString;
- (void)href:(NSString *_Nonnull)jsString;
- (void)hrefForResult:(NSString *_Nonnull)jsString;
- (void)setItem:(NSString *_Nonnull)jsString;
- (void)showToast:(NSString *_Nonnull)alertString;
- (void)getUser:(NSString *_Nonnull)jsString;
- (void)back;//
- (void)backForResult;
- (void)setResultSuccess;
@end
@interface WebViewBaseController:BaseViewController<JSWebViewControllerExprot,UIWebViewDelegate,WKNavigationDelegate,WKUIDelegate,WKScriptMessageHandler>
{
}
@property (strong,nonatomic,nonnull) UIWebView *webView;
@property (strong,nonatomic,nonnull) WKWebView *wkwebView;
@property (strong,nonatomic,nonnull) WKUserContentController *userContro;
@property (strong,nonatomic,nonnull) WKWebViewConfiguration *wkWebViewConfig;
@property (nonnull,strong,nonatomic) JSContext *context;
上面的是声明
下面到了实现文件中
这边的两个方法分别使用
-(IE_INSTANCE)init
{
self = [super init];
if (self)
{
[self createWebView];
}
return self;
}
-(void)createWebView
{
if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_8_4) {
[self createWkWebView];
} else {
[self createUIWebView];
}
}
-(void)createUIWebView
{
if (!_webView) {
self.webView = [[UIWebView alloc]init];
self.webView.delegate = self;
[self.view addSubview:_webView];
self.context =[self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.context[@"jGate"] = self; //这边就是注入 很重要的
}
[self.view addSubview:_webView];
}
-(void)createWkWebView
{
if (!self.wkwebView)
{
self.wkWebViewConfig = [[WKWebViewConfiguration alloc]init];
self.wkWebViewConfig.preferences = [[WKPreferences alloc]init];
self.wkWebViewConfig.preferences.minimumFontSize = 10;
self.wkWebViewConfig.preferences.javaScriptCanOpenWindowsAutomatically = false;
self.wkWebViewConfig.preferences.javaScriptEnabled = true; //
_userContro = [[WKUserContentController alloc]init];
[_userContro addScriptMessageHandler:self name:@"jGate"];
self.wkWebViewConfig.userContentController = _userContro;
self.wkwebView = [[WKWebView alloc] initWithFrame:CGRectMake(0, UINavgationBarHeight+UIAPPliacationStateBarHeight, ScreenWidth, ScreenHeight) configuration:self.wkWebViewConfig];
self.wkwebView.backgroundColor = [UIColor whiteColor];
}
上面着急为红色的部分就是 JS注入 稍后会出一个js大概的思路
//下面要说的着重就是交互 就是JS和OC的数据来回传递
UIWebView的介绍:
如果是UIWEBView的js回调到OC那么就直接在头文件上申明就是头部蓝色文字的地方。(格式也很重要)
-
(void)postMvc:(NSString * _Nonnull)jsString;(注意jsString)目前个人测试通过的是json格式的一个字符串 这个是js回调到OC
-(void)ocToJS:(NSDictionary*)dic
{
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic
options:NSJSONWritingPrettyPrinted
error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
return jsonString;
NSString *resultString = [NSString stringWithFormat:@"Pcm.custom.Ajax.fireListener(%@)",[self stringFromDictionary:dic]];[self.context evaluateScript:resultString];
}
下面说一下WKWEBview的使用
-
(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
[webView evaluateJavaScript:@"document.title" completionHandler:^(id a, NSError *e) {
NSLog(@"title is %@",a);
self.title = (NSString *)a;
[self setTitleLabel];
}];
}
开启alert弹窗
} - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message
message:nil
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
completionHandler();
}]];
[self presentViewController:alertController animated:YES completion:^{}];
}
可以看出这里是同意进行处理
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
//查看message.body里面的内容 , 同样也是一个json字符串格式
NSDictionary *dic = [self dictionaryFromString:message.body];
NSString *jsstring = nil;
if([[dic allKeys] containsObject:@"params"])
{
NSDictionary *jsDictionary = dic[@"params"];
jsstring = [self stringFromDictionary:jsDictionary];
}
if ([dic[@"method"] isEqualToString:@"postMvc"])
{
[self postMvc:jsstring];
}
else if([dic[@"method"] isEqualToString:@"href"])
{
[self href:jsstring];
}
else if([dic[@"method"] isEqualToString:@"hrefForResult"])
{
[self hrefForResult:jsstring];
}
else if([dic[@"method"] isEqualToString:@"back"])
{
[self backController];
} else if([dic[@"method"] isEqualToString:@"setItem"])
{
[self setItem:jsstring];
}
else if([dic[@"method"] isEqualToString:@"getUser"])
{
[self getUser:jsstring];
}
else if([dic[@"method"] isEqualToString:@"backForResult"])
{
[self backForResult];
}
else if([dic[@"method"] isEqualToString:@"setResultSuccess"])
{
[self setResultSuccess];
}
}
我们再说这里代入的一个问题 就是加载本地资源,进行本地URL后面加参数
if (self.wkwebView)
{
if ([jsString isKindOfClass:[NSNull class]] )
{
jsString = @"";
}else
{
jsString = [jsString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval a=[dat timeIntervalSince1970];
float secode = a +10;
NSString *sourceString = [NSString stringWithFormat:@"document.cookie = 'params = %@;expires=%@;path=/'",jsString, [NSString stringWithFormat:@"%.0f", secode]];
WKUserScript * cookieScript = [[WKUserScript alloc]
initWithSource:sourceString
injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[self.userContro addUserScript:cookieScript];
self.wkwebView.configuration.userContentController = self.userContro;
NSError *error;
NSString *html = [NSString stringWithContentsOfFile:url encoding:NSUTF8StringEncoding error:&error];
NSURL *baseURL = [NSURL fileURLWithPath:url];
[self.wkwebView loadHTMLString:html baseURL:baseURL];
}
else
{
jsString = [jsString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *urlString = [NSString stringWithFormat:@"%@?params=%@",
url,
jsString];
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]] ];
}
UIWebView的[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]] ]这边的request可以加载 统一资源定位器,也就是可以添加参数。
WKWebView 的loadRequest方法只能是 固定的网址(eg。www.baidu.com) 所以这里使用了一个Document的一个cookie来进行传参数。通过实践是可以成功的,不过这里需要进行一次URL编码。js里面还要进行一次解码。
可以留言与我探讨,文章为本人实践所做,如有错误还请指正。
网友评论