简单说说iOS之WKWebView的用法小结

WKWebView的优势

  • 性能高,稳定性好,占用的内存比较小,
  • 支持JS交互
  • 支持HTML5 新特性
  • 可以添加进度条(然并卵,不好用,还是习惯第三方的)。
  • 支持内建手势,
  • 据说高达60fps的刷新频率(不卡)

1.Xcode新建My.html文件,自定义html内容,主要代码如下:

(1)标签为UI样式(写了简单的JS代码,目的用于讲解交互)

(2)onClick为JS事件,当JS想给OC传递参数时,采用如下代码:window.webkit.messageHandlers.<方法名>.postMessage(数据)

<h1 style="text-align:center;background-color: #e6b500;wdith:100px;height:40px">欢迎来到JS世界</h1>

 <p style="text-align:center"> <a href="github://callName_?https://github.com/wslcmk" rel="external nofollow" >Github主页</a> :截获URL调用OC</p>

<p style="text-align:center"> <a href="http://192.168.0.116/monkey/iOS-URNetworking/commits/master" rel="external nofollow" >GitLab主页</a> </p>
<p style="text-align:center"> <button id="btn1" type = "button" onclick = "jsToOcFunctionOne()" > JS调用OC->不带参数 </button> </p>

<p style="text-align:center"> <button id="btn2" type = "button" onclick = "jsToOcFunctionTwo()"> JS调用OC->带参数 </button> </p>

<p style="text-align:center"> <button id="btn3" type = "button" onclick = "showAlert()" > oc捕获到html的弹出框 </button> </p>

<!--    JS语法-->
<script type = "text/javascript">

function jsToOcFunctionOne()
{
  window.webkit.messageHandlers.jsToOcNoPrams.postMessage({});
}

function jsToOcFunctionTwo()
{
  window.webkit.messageHandlers.jsToOcWithPrams.postMessage({"params":"我是JS参数"});
}

function showAlert()
{
  alert("我来自JS世界,被你发现了");
}

//改变背景色
function changeBgColor()
{
  document.body.style.backgroundColor = randomColor();
}

2.KVO实现加载进度条以及标题

//  KVO监听:获取进度并显示 获取标题并显示
  [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
  [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
  if ([keyPath isEqualToString:@"title"]&&object == _webView) {
    self.title = _webView.title;
  }else if ([keyPath isEqualToString:@"estimatedProgress"]
       && object == _webView)
  {
    self.progressView.progress = _webView.estimatedProgress;
    if (_webView.estimatedProgress >= 1.0f) {
      dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)),
             dispatch_get_main_queue(), ^{
               self.progressView.progress = 0;
             });
    }
  }
}

3.通过拦截url方式,JS调用OC代码,决定是否跳转(WKNavigationDelegate代理)

#pragma mark -- WKNavigationDelegate  WKNavigationDelegate主要处理一些跳转、加载处理操作
// 根据WebView对于即将跳转的HTTP请求头信息和相关信息来决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

  NSString * urlStr = navigationAction.request.URL.absoluteString;
  NSLog(@"发送跳转请求:%@",urlStr);
  //自己定义的协议头
  NSString *htmlHeadString = @"github://";
  if([urlStr hasPrefix:htmlHeadString]){
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"通过截取URL调用OC" message:@"前往Github?" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {

    }])];
    [alertController addAction:([UIAlertAction actionWithTitle:@"打开" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
      NSURL * url = [NSURL URLWithString:[urlStr stringByReplacingOccurrencesOfString:@"github://callName_?" withString:@""]];
      [[UIApplication sharedApplication]canOpenURL:url];
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
    decisionHandler(WKNavigationActionPolicyCancel);
  }else{
    decisionHandler(WKNavigationActionPolicyAllow);
  }
}

4.OC获取JS alert内容(WKUIDelegate处理警告、输入、以及确认,这里只列举了alert。输入和确认就不一一列举了,分别是JS端confirm和prompt函数触发)

当调用JS端alert函数时:通过如下代理获取alert内容

#pragma mark -- WKUIDelegate WKUIDelegate主要处理JS脚本,确认框,警告框等
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
  UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"JS-alert-Action" message:message?:@"" preferredStyle:UIAlertControllerStyleAlert];
  [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    completionHandler();
  }])];
  [self presentViewController:alertController animated:YES completion:nil];
}

5.OC调用JS代码,实现改变JS页面颜色(通过evaluateJavaScript函数、jsString为JS端方法名)

#pragma mark -navigationItem Action
- (void)ocToJs
{
  // changeColor()是JS方法名
  NSString *jsString = [NSString stringWithFormat:@"changeBgColor()"];
  [_webView evaluateJavaScript:jsString completionHandler:^(id _Nullable data, NSError * _Nullable error) {

  }];
}

6.通过接受JS方法名捕捉方法(带参数和不带参数,JS端向IOS传递参数,采用window.webkit.messageHandlers.<方法名>.postMessage(数据))

(1)需要引入WKUserContentController、主要代码如下

//创建网页配置对象
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    WKUserContentController * wkUController = [[WKUserContentController alloc] init];
    //注册一个name为jsToOcNoPrams的js方法 设置处理接收JS方法的对象
    [wkUController addScriptMessageHandler:self name:@"jsToOcNoPrams"];
    [wkUController addScriptMessageHandler:self name:@"jsToOcWithPrams"];
    config.userContentController = wkUController;

(2)核心代码

#pragma mark - 通过接收JS传出消息的name进行捕捉的回调方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
  NSLog(@"name:%@\\\\n body:%@\\\\n frameInfo:%@\\\\n",message.name,message.body,message.frameInfo);
  //用message.body获得JS传出的参数体
  NSDictionary * parameter = message.body;
  //JS调用OC
  if([message.name isEqualToString:@"jsToOcNoPrams"]){
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js调用到了oc" message:@"不带参数" preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    }])];
    [self presentViewController:alertController animated:YES completion:nil];

  }else if([message.name isEqualToString:@"jsToOcWithPrams"]){
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"js调用到了oc" message:parameter[@"params"] preferredStyle:UIAlertControllerStyleAlert];
    [alertController addAction:([UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
    }])];
    [self presentViewController:alertController animated:YES completion:nil];
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • iOS中WKWebView白屏问题的分析与解决

    前言 随着WKWebView的推出, 解决了很多UIWebView 的问题.比如加载速度慢,内存泄露等问题.WKWebView是在iOS 8 推出,前段时间正好把项目也适配到iOS 8 以上了,终于可以把项目中的UIWebView 替换成WKWebView. WKWebView的特点: 性能高,稳定性好,占用的内存比较小, 支持JS交互 支持HTML5 新特性 可以添加进度条(然并卵,不好用,还是习惯第三方的). 支持内建手势, 据说高达60fps的刷新频率(不卡) 但是发现在使用的时候还是有很

  • iOS11 WKWebView问题汇总

    问题一描述: iOS9和iOS10用WKWebView加载URL都没有问题,iOS11却是一片空白 可能是用了NSMutableURLRequest,iOS11貌似不支持NSMutableURLRequest,无论是用UIWebView还是WKWebView,都不支持NSMutableURLRequest 解决方法参考 if #available(iOS 11, *) { let request = NSURLRequest.init(url: URL.init(string: urlStr)!

  • ios wkwebview离线化加载h5资源解决方案

    思路: 使用NSURLProtocol拦截请求转发到本地. 1.确认离线化需求 部门负责的app有一部分使用的线上h5页,长期以来加载略慢... 于是考虑使用离线化加载. 确保[低速网络]或[无网络]可网页秒开. 2.使用[NSURLProtocol]拦截 区别于uiwebview wkwebview使用如下方法拦截 @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [su

  • iOS中wkwebView内存泄漏与循环引用问题详解

    前言 现在大多数网络也面加载都会用到wkwebview,之前在使用wkwebview的时候,网上很多的基础教程使用很多只是说了怎么添加Message Handler 但是并没有告诉到家有这个内存泄漏的风险,如果你只是也没内的数据调用你压根都不会发现这个问题.没存泄漏这个问题说大不大,说小不小,严重的话话直接到时app闪退,所以还是得重视起.好下面说一下怎么解决,话不多说了,来一起看看详细的介绍吧 解决方法 1,在做网页端js交互的时候 我们都会这样去添加js [self.customWebVie

  • iOS中WKWebView的一些特殊使用总结

    前言 现在大部分的app只支持iOS8以上的系统了,在接入H5时可以只管最新的WKWebView了. WKWebView的优势 性能高,稳定性好,占用的内存比较小, 支持JS交互 支持HTML5 新特性 可以添加进度条(然并卵,不好用,还是习惯第三方的). 支持内建手势, 据说高达60fps的刷新频率(不卡) 本文将给大家总结下iOS中WKWebView的一些特殊使用,下面话不多说了,来一起看看详细的介绍吧 WKWebView 加载本地网页的方式 1.直接加载字符串 - (void)loadHT

  • ios下OC与JS交互之WKWebView

    上一篇文章我们使用了JavaScriptCore框架重写了之前的示例,iOS8苹果偏爱HTML5,重构了UIWebVIew,给我们带来了WKWebView,使其性能.稳定性.功能大幅度提升,也更好的支持了HTML5的新特性.这篇文章就们就拿WKWebView来小试牛刀 一.WKWebView Framework WKWebView的14个类与3个协议: WKBackForwardList: 之前访问过的 web 页面的列表,可以通过后退和前进动作来访问到. WKBackForwardListIt

  • iOS11 WKWebView 无法加载内容的解决方法

    问题描述: iOS9和iOS10用WKWebView加载URL都没有问题,iOS11却是一片空白 可能是用了 NSMutableURLRequest ,iOS11貌似不支持 NSMutableURLRequest ,无论是用 UIWebView 还是 WKWebView ,都不支持 NSMutableURLRequest 解决方法参考 if #available(iOS 11, *) { let request = NSURLRequest.init(url: URL.init(string:

  • 简单说说iOS之WKWebView的用法小结

    WKWebView的优势 性能高,稳定性好,占用的内存比较小, 支持JS交互 支持HTML5 新特性 可以添加进度条(然并卵,不好用,还是习惯第三方的). 支持内建手势, 据说高达60fps的刷新频率(不卡) 1.Xcode新建My.html文件,自定义html内容,主要代码如下: (1)标签为UI样式(写了简单的JS代码,目的用于讲解交互) (2)onClick为JS事件,当JS想给OC传递参数时,采用如下代码:window.webkit.messageHandlers.<方法名>.post

  • iOS开发之枚举用法小结

    前言 Enum,也就是枚举,从C语言开始就有了,C++.Java.Objective-C.Swift这些语言,当然都有对应的枚举类型,功能可能有多有少,但是最核心的还是一个-规范的定义代码中的状态.选项等"常量". 举个例子,我们想要在开发中根据四季的变化做不同的操作,我们首先想到的可能会是定义一个int型变量,通过为该变量赋不同的值来表示四季(e.g. 1为春天,2为夏天,3为秋天,4为冬天).但是,对于阅读该份代码的人来讲,他们并不能在短时间内就明白数字1234所代表的具体含义.这

  • Java中String.split()用法小结

    在java.lang包中有String.split()方法,返回是一个数组 我在应用中用到一些,给大家总结一下,仅供大家参考: 1.如果用"."作为分隔的话,必须是如下写法,String.split("\\."),这样才能正确的分隔开,不能用String.split("."); 2.如果用"|"作为分隔的话,必须是如下写法,String.split("\\|"),这样才能正确的分隔开,不能用String.s

  • 详解PHP中cookie和session的区别及cookie和session用法小结

    具体来说 cookie 是保存在"客户端"的,而session是保存在"服务端"的 cookie 是通过扩展http协议实现的 cookie 主要包括 :名字,值,过期时间,路径和域: 如果cookie不设置生命周期,则以浏览器关闭而关闭,这种cookie一般存储在内存而不是硬盘上.若设置了生命周期则相反,不随浏览器的关闭而消失,这些cookie仍然有效直到超过设定的过 期 时间. session 一种类似散列表的形式保存信息, 当程序需要为某个客户端的请求创建一个

  • javaScript产生随机数的用法小结

    var chars = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']; function generateMixed(n) { var res = ""; for(var i = 0; i < n ; i ++) { var id = M

  • iOS中 valueForKeyPath常用用法

    1.valueForKeyPath可以获取数组中的最小值.最大值.平均值.求和.代码如下: NSArray *array = @[@10, @23, @43, @54, @7, @17, @5]; + (NSString *)caculateArray:(NSArray *)array { CGFloat sum = [[array valueForKeyPath:@"@sum.floatValue"] floatValue]; CGFloat avg = [[array valueF

  • C/C++ 中const关键字的用法小结

    C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性. Const作用 NO. 作用 说明 参考 1 可以定义const常量 const int Max = 100; 2 便于进行类型检查 const常量有数据类型,而宏常量没有数据类型.编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误 void f(const int i) { ---} //对传入的参数进行类型检查,不匹配进行提示 3 可以保护被修

  • C++语言中std::array的用法小结(神器用法)

    摘要:在这篇文章里,将从各个角度介绍下std::array的用法,希望能带来一些启发. td::array是在C++11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能.也正因此,使得std::array有很多与其他容器不同的特殊之处,比如:std::array的元素是直接存放在实例内部,而不是在堆上分配空间:std::array的大小必须在编译期确定:std::array的构造函数.析构函数和赋值操作符都是编译器隐式声明的--这让很多用惯了std::vector这类容器的程

  • vue filter的四种用法小结

    目录 filter的用法小结 filter的基本用法 filter的用法小结 使用计算属性app.js var app5 = new Vue({     el: '#app5',     data: {         shoppingList: [             "Milk", "Donuts", "Cookies", "Chocolate", "Peanut Butter", "Pe

  • C#中AutoResetEvent控制线程用法小结

    目录 AutoResetEvent主要方法及实践 第二种方法Semaphore 第三种方法,约定每个线程只干自己的事 第四种方法 Mutex 本文主要来自一道面试题,由于之前对AutoResetEvent的概念比较模糊(即使已经使用过了).面试题题目很简洁:两个线程交替打印0~100的奇偶数.你可以先动手试试,我主要是尝试在一个方法里面完成这个任务. 注: Suspend,Resume来控制线程已经在.net framework2.0被淘汰了,原因就是挂起之后,但因为异常而没有及时恢复,如果占用

随机推荐