美文网首页
浅谈WKWebView

浅谈WKWebView

作者: JiangDaDaaa | 来源:发表于2019-01-08 15:27 被阅读0次

    由于项目经常性会使用到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:^{
            
        }];
    }
    

    相关文章

      网友评论

          本文标题:浅谈WKWebView

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