美文网首页
uiwebview WKwebView

uiwebview WKwebView

作者: 问问问你 | 来源:发表于2018-02-27 15:57 被阅读20次

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里面还要进行一次解码。
可以留言与我探讨,文章为本人实践所做,如有错误还请指正。

相关文章

网友评论

      本文标题:uiwebview WKwebView

      本文链接:https://www.haomeiwen.com/subject/ngutgxtx.html