浅谈WKWebView

2019-01-08  本文已影响0人  JiangDaDaaa

由于项目经常性会使用到WKWebView,于是在这里记录下一下关于苹果WKWebView的要点与遇到的问题


基本配置

使用WKWebView之前需要先导入 #import <WebKit/WebKit.h>

//配置WKWebViewConfiguration
    注意加上WKScriptMessageHandler

    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    //WKUserContentController 主要用于与JS交互
    config.userContentController = [[WKUserContentController alloc] init];
    [config.userContentController addScriptMessageHandler:self name:@"xxx"];

// 创建WKPreferences
        WKPreferences *preference = [[WKPreferences alloc]init];
        //最小字体大小 当将javaScriptEnabled属性设置为NO时,可以看到明显的效果
        preference.minimumFontSize = 0;
        //设置是否支持javaScript 默认是支持的
        preference.javaScriptEnabled = YES;
        // 在iOS上默认为NO,表示是否允许不经过用户交互由javaScript自动打开窗口
        preference.javaScriptCanOpenWindowsAutomatically = YES;
        config.preferences = preference;
  
//创建WKWebView
    注意写上WKUIDelegate,WKNavigationDelegate
    _webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) configuration:config];
    //不显示滚动条
    _webView.scrollView.showsVerticalScrollIndicator = NO;
    _webView.scrollView.showsHorizontalScrollIndicator = NO;
    //设置代理
    _webView.navigationDelegate = self;
    _webView.UIDelegate = self;

核心代理方法

webview最主要是使用下面的方法与js进行交互

JS端
<script>
let body = {
  method1 = "hello world"
}
window.webkit.messageHandlers.xxx.postMessage(body)
</script>
//其中xxx为JS与iOS双方规定的相同字符串,body为传入iOS端的参数

iOS端
-(void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
  if ([message.name isEqualToString:@"xxx"]) {
      if [(message.body["method1"] isEqualToString:@"hello world"]) {
            //进行逻辑处理
      }
  }
}

关于webView传参给JS

WKWebView传参给JS主要靠evaluateJavaScript方法,由于接触JS比较少,传参也着实费了一番功夫才弄明白

1.传入String类型

这个类型是最简单的

[webView evaluateJavaScript:[NSString stringWithFormat:@"JSCallBack('%@')",str] completionHandler:^(id _Nullable object, NSError * _Nullable error) { }
];

2.传入Array类型

[webView evaluateJavaScript:[NSString stringWithFormat:@"JSCallBack(%@)",array] completionHandler:^(id _Nullable object, NSError * _Nullable error) { }
];

3.传入Dictionary类型

字典类型的需要转换为json字符串再传,并且去掉空格跟换行符
    NSData *data1 = [NSJSONSerialization dataWithJSONObject:dic 
                  options:NSJSONWritingPrettyPrinted error:nil];
     NSString *jsonStr = [[NSString alloc] initWithData:data1 
                      encoding:NSUTF8StringEncoding];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@" " withString:@""];
    jsonStr = [jsonStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    [webView evaluateJavaScript:[NSString stringWithFormat:@"JSCallBack('%@')",jsonStr] completionHandler:^(id _Nullable object, NSError * _Nullable error) {

   }];

关于使用Masonry时webview显示不完全的问题

有时候webview加载出来的页面会跟预期的有偏差,比如位置变了,大小变了,这些时候只能在loadRequest之前使用Masonry,将webview约束好

    [_webView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(UIEdgeInsetsZero);
    }];

    [_webView loadRequest:request];

关于userAgent

有时候应服务端要求,需要给webView自定义userAgent,这里涉及到了html端与后端的获取,正常获取逻辑是这样的

 [_webView evaluateJavaScript:"navigator.userAgent" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
 NSString *cusUserAgent = [NSString stringWithFormat:@"%@ %@",result,@"customMethod"];
_webView.customUserAgent = cusUserAgent;
  }];

这样子看起来似乎没什么问题,后端可以获取的到,但是html端并不可以获取到已经修改后的userAgent,具体原因小生也找不出来。。。

解决办法

我解决的办法是,创建两个webView,利用其中一个获取userAgent,另外一个在第一个获取到的时候,使用第一个的UserAgent,利用第二个webview进行之后的逻辑操作

    //注意,这两个webview都已经初始化,网上有一些说初始化之前调用,是不可以的。
    [_webView1 evaluateJavaScript:@"navigator.userAgent" completionHandler:
    ^(id _Nullable result, NSError * _Nullable error) {
        NSString *cusAgent = [result stringByAppendingString:@"customMethod"];
        _webView2.customUserAgent = cusAgent;
    }];

    NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                  customAgent, @"UserAgent", nil];
    [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];
    [[NSUserDefaults standardUserDefaults] synchronize];

其他

这里记录一下一些可能会用到的方法

删除缓存

- (void)deleteWebCache {
    //allWebsiteDataTypes清除所有缓存
    NSSet *websiteDataTypes = [WKWebsiteDataStore allWebsiteDataTypes];
    
    NSDate *dateFrom = [NSDate dateWithTimeIntervalSince1970:0];
    
    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:websiteDataTypes modifiedSince:dateFrom completionHandler:^{
        
    }];
}
上一篇下一篇

猜你喜欢

热点阅读