欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS-WKWebView的使用

程序员文章站 2022-05-21 10:57:24
参考文章:http://www.cocoachina.com/ios/20180831/24753.html WK时苹果在iOS8.0之后推出的控件,相比于UIWebView: 内存消耗少; 解决了网页加载时的内存泄漏问题; 与HTML页面的交互更方便; 总之,其性能比UIWebView好很多。 使 ......

参考文章:

 

wk时苹果在ios8.0之后推出的控件,相比于uiwebview:

  • 内存消耗少;
  • 解决了网页加载时的内存泄漏问题;
  • 与html页面的交互更方便;
  • 总之,其性能比uiwebview好很多。

使用时,首先要添加头文件:

#import <webkit/webkit.h>

简单创建一个wkwebview:

    self.iwkwebview = [[wkwebview alloc]initwithframe:cgrectmake(0, 64, [uiscreen mainscreen].bounds.size.width, [uiscreen mainscreen].bounds.size.height-64)];
    //此处协议下面会讲到
    self.iwkwebview.navigationdelegate = self;
    self.iwkwebview.uidelegate = self;
    self.iwkwebview.allowsbackforwardnavigationgestures = yes;
    nsurl *url = [nsurl urlwithstring:@"https://www.baidu.com"];
    nsurlrequest *request = [nsurlrequest requestwithurl:url];
    [self.iwkwebview loadrequest:request];
    [self.view addsubview:self.iwkwebview];

基本用法和uiwebview差不多。

这里介绍几个主要的类:

  • wkwebview
  • wkwebviewconfiguration

  • wkpreferences

  • wkusercontentcontroller

  • wkwebsitedatastore


 

 

1. wkwebview:

常用属性:

// 导航代理
@property (nullable, nonatomic, weak) id <wknavigationdelegate> navigationdelegate;
// ui代理
@property (nullable, nonatomic, weak) id <wkuidelegate> uidelegate;
// 页面标题, 一般使用kvo动态获取
@property (nullable, nonatomic, readonly, copy) nsstring *title;
// 页面加载进度, 一般使用kvo动态获取
@property (nonatomic, readonly) double estimatedprogress;
// 可返回的页面列表, 已打开过的网页, 有点类似于navigationcontroller的viewcontrollers属性
@property (nonatomic, readonly, strong) wkbackforwardlist *backforwardlist;
// 页面url
@property (nullable, nonatomic, readonly, copy) nsurl *url;
// 页面是否在加载中
@property (nonatomic, readonly, getter=isloading) bool loading;
// 是否可返回
@property (nonatomic, readonly) bool cangoback;
// 是否可向前
@property (nonatomic, readonly) bool cangoforward;
// wkwebview继承自uiview, 所以如果想设置scrollview的一些属性, 需要对此属性进行配置
@property (nonatomic, readonly, strong) uiscrollview *scrollview;
// 是否允许手势左滑返回上一级, 类似导航控制的左滑返回
@property (nonatomic) bool allowsbackforwardnavigationgestures;
//自定义useragent, 会覆盖默认的值 ,ios 9之后有效
@property (nullable, nonatomic, copy) nsstring *customuseragent

常用方法:

// 带配置信息的初始化方法
// configuration 配置信息
- (instancetype)initwithframe:(cgrect)frame configuration:(wkwebviewconfiguration *)configuration
// 加载请求
- (nullable wknavigation *)loadrequest:(nsurlrequest *)request;
// 加载html
- (nullable wknavigation *)loadhtmlstring:(nsstring *)string baseurl:(nullable nsurl *)baseurl;
// 返回上一级
- (nullable wknavigation *)goback;
// 前进下一级, 需要曾经打开过, 才能前进
- (nullable wknavigation *)goforward;
// 刷新页面
- (nullable wknavigation *)reload;
// 根据缓存有效期来刷新页面
- (nullable wknavigation *)reloadfromorigin;
// 停止加载页面
- (void)stoploading;
// 执行javascript代码
- (void)evaluatejavascript:(nsstring *)javascriptstring completionhandler:(void (^ _nullable)(_nullable id, nserror * _nullable error))completionhandler;

 

2. wkwebviewconfiguration:配置信息

可以用配置信息来初始化wkwebview.

属性有:

    //关于网页的设置
    @property (nonatomic, strong) wkpreferences *preferences;
    //javascript与原生交互的桥梁
    @property (nonatomic, strong) wkusercontentcontroller *usercontentcontroller;
    //提供了网站所能使用的数据类型
    @property (nonatomic, strong) wkwebsitedatastore *websitedatastore api_available(macosx(10.11), ios(9.0));
    //是否允许播放媒体文件
    @property (nonatomic) bool allowsairplayformediaplayback api_available(macosx(10.11), ios(9.0));
    //是使用h5的视频播放器在线播放, 还是使用原生播放器全屏播放
    @property (nonatomic) bool allowsinlinemediaplayback;
    //需要用户允许才能播放的媒体类型
    @property (nonatomic) wkaudiovisualmediatypes mediatypesrequiringuseractionforplayback api_available(macosx(10.12), ios(10.0));

 

2.1  wkpreference:

   wkpreferences *preference = [[wkpreferences alloc]init];
    //最小字体大小
    preference.minimumfontsize = 0;
    //是否支持javascript,默认yes
    preference.javascriptenabled = yes;
    //是否允许不经过用户交互由javascript自动打开窗口
    preference.javascriptcanopenwindowsautomatically = yes;

 

2.2  wkusercontentcontroller

// 注入javascript与原生交互协议
// js 端可通过 window.webkit.messagehandlers..postmessage() 发送消息
- (void)addscriptmessagehandler:(id <wkscriptmessagehandler>)scriptmessagehandler name:(nsstring *)name;
// 移除注入的协议, 在deinit方法中调用
- (void)removescriptmessagehandlerforname:(nsstring *)name;
// 通过wkuserscript注入需要执行的javascript代码
- (void)adduserscript:(wkuserscript *)userscript;
// 移除所有注入的javascript代码
- (void)removealluserscripts;

使用wkusercontentcontroller注入的交互协议, 需要遵循wkscriptmessagehandler协议, 在其协议方法中获取javascript端传递的事件和参数:

- (void)usercontentcontroller:(wkusercontentcontroller *)usercontentcontroller didreceivescriptmessage:(wkscriptmessage *)message;
wkscriptmessage包含了传递的协议名称及参数, 主要从下面的属性中获取:
// 协议名称, 即上面的add方法传递的name
@property (nonatomic, readonly, copy) nsstring *name;
// 传递的参数
@property (nonatomic, readonly, copy) id body;

 

2.3  wkwebsitedatastore

wkwebsitedatastore 提供了网站所能使用的数据类型,包括 cookies,硬盘缓存,内存缓存活在一些websql的数据持久化和本地持久化。可通过 wkwebviewconfiguration类的属性 websitedatastore 进行相关的设置。wkwebsitedatastore相关的api也比较简单:

// 默认的data store
+ (wkwebsitedatastore *)defaultdatastore;
// 如果为webview设置了这个data store,则不会有数据缓存被写入文件
// 当需要实现隐私浏览的时候,可使用这个
+ (wkwebsitedatastore *)nonpersistentdatastore;
// 是否是可缓存数据的,只读
@property (nonatomic, readonly, getter=ispersistent) bool persistent;
// 获取所有可使用的数据类型
+ (nsset<nsstring *> *)allwebsitedatatypes;
// 查找指定类型的缓存数据
// 回调的值是wkwebsitedatarecord的集合
- (void)fetchdatarecordsoftypes:(nsset<nsstring *> *)datatypes completionhandler:(void (^)(nsarray<wkwebsitedatarecord *> *))completionhandler;
// 删除指定的纪录
// 这里的参数是通过上面的方法查找到的wkwebsitedatarecord实例获取的
- (void)removedataoftypes:(nsset<nsstring *> *)datatypes fordatarecords:(nsarray<wkwebsitedatarecord *> *)datarecords completionhandler:(void (^)(void))completionhandler;
// 删除某时间后修改的某类型的数据
- (void)removedataoftypes:(nsset<nsstring *> *)websitedatatypes modifiedsince:(nsdate *)date completionhandler:(void (^)(void))completionhandler;
// 保存的http cookies
@property (nonatomic, readonly) wkhttpcookiestore *httpcookiestore

datatypes:

// 硬盘缓存
wkwebsitedatatypediskcache,
// html离线web应用程序缓存
wkwebsitedatatypeofflinewebapplicationcache,
// 内存缓存
wkwebsitedatatypememorycache,
// 本地缓存
wkwebsitedatatypelocalstorage,
// cookies
wkwebsitedatatypecookies,
// html会话存储
wkwebsitedatatypesessionstorage,
//  indexeddb 数据库
wkwebsitedatatypeindexeddbdatabases,
// websql 数据库
wkwebsitedatatypewebsqldatabases

datarecord:

// 展示名称, 通常是域名
@property (nonatomic, readonly, copy) nsstring *displayname;
// 包含的数据类型
@property (nonatomic, readonly, copy) nsset<nsstring *> *datatypes;

关于此类的简单使用:

1.删除指定时间的所有类型数据

    nsset *websitedatatypes = [wkwebsitedatastore allwebsitedatatypes];
    nsdate *datefrom = [nsdate datewithtimeintervalsince1970:0];
    [[wkwebsitedatastore defaultdatastore] removedataoftypes:websitedatatypes modifiedsince:datefrom completionhandler:^{
        // done
        nslog(@"释放");
    }];

 

2.查找删除

    wkwebsitedatastore *datastore = [wkwebsitedatastore defaultdatastore];
    [datastore fetchdatarecordsoftypes:[wkwebsitedatastore allwebsitedatatypes] completionhandler:^(nsarray<wkwebsitedatarecord *> * _nonnull records) {
        for (wkwebsitedatarecord *record in records) {
            [datastore removedataoftypes:record.datatypes fordatarecords:@[record] completionhandler:^{
                // done
            }];
        }
    }];

 

3.查找删除特定的内容

   wkwebsitedatastore *datastore = [wkwebsitedatastore defaultdatastore];
    [datastore fetchdatarecordsoftypes:[wkwebsitedatastore allwebsitedatatypes] completionhandler:^(nsarray<wkwebsitedatarecord *> * _nonnull records) {
        for (wkwebsitedatarecord *record in records) {
            if ([record.displayname isequaltostring:@"baidu"]) {
                [datastore removedataoftypes:record.datatypes fordatarecords:@[record] completionhandler:^{
                    // done
                }];
            }
        }
    }];

 

wknavigationdelegate:

iOS-WKWebView的使用
#pragma mark - wknavigationdelegate

//请求加载之前,决定是否跳转
- (void)webview:(wkwebview *)webview decidepolicyfornavigationaction:(wknavigationaction *)navigationaction decisionhandler:(void (^)(wknavigationactionpolicy))decisionhandler{
    nslog(@"加载前允许跳转");
    decisionhandler(wknavigationactionpolicyallow);
}
//开始加载时调用
- (void)webview:(wkwebview *)webview didstartprovisionalnavigation:(null_unspecified wknavigation *)navigation{
    nslog(@"开始加载");
}
//收到响应开始加载后,决定是否跳转
- (void)webview:(wkwebview *)webview decidepolicyfornavigationresponse:(wknavigationresponse *)navigationresponse decisionhandler:(void (^)(wknavigationresponsepolicy))decisionhandler{
    nslog(@"收到响应后允许跳转");
    decisionhandler(wknavigationresponsepolicyallow);
}
//内容开始返回时调用
- (void)webview:(wkwebview *)webview didcommitnavigation:(null_unspecified wknavigation *)navigation{
    nslog(@"开始返回内容");
}
//加载完成时调用
- (void)webview:(wkwebview *)webview didfinishnavigation:(null_unspecified wknavigation *)navigation{
    nslog(@"加载完成");
    self.title = webview.title;
}
//加载失败调用
- (void)webview:(wkwebview *)webview didfailprovisionalnavigation:(null_unspecified wknavigation *)navigation witherror:(nserror *)error{
    nslog(@"加载失败");
}

//收到服务器重定向请求后调用
- (void)webview:(wkwebview *)webview didreceiveserverredirectforprovisionalnavigation:(null_unspecified wknavigation *)navigation{
    nslog(@"服务器重定向");
}
//当main frame最后下载数据失败时,会回调
- (void)webview:(wkwebview *)webview didfailnavigation:(null_unspecified wknavigation *)navigation witherror:(nserror *)error{
     nslog(@"返回内容发生错误");
}

//用于授权验证的api,与afn、uiwebview的授权验证api是一样的
- (void)webview:(wkwebview *)webview didreceiveauthenticationchallenge:(nsurlauthenticationchallenge *)challenge completionhandler:(void (^)(nsurlsessionauthchallengedisposition disposition, nsurlcredential * _nullable credential))completionhandler{
    completionhandler(nsurlsessionauthchallengeperformdefaulthandling,nil);
}

//当web content处理完成时,会回调
- (void)webviewwebcontentprocessdidterminate:(wkwebview *)webview api_available(macosx(10.11), ios(9.0)){
    nslog(@"webcontent完成");
}
view code

 

这里放一个完整的wkwebview例子,仅供参考:

//初始化wkpreferences,并设置相关属性
    wkpreferences *preference = [[wkpreferences alloc]init];
    
    //初始化wkusercontentcontroller,并设置相关属性
    wkusercontentcontroller *usercontroller = [[wkusercontentcontroller alloc]init];
//    添加在js中操作的对象名称,通过该对象来向web view发送消息
//    js 端可通过 window.webkit.messagehandlers..postmessage() 发送消息
//    <script type="text/javascript">
//    function clickbtn(){
//        var dict = {"name":"tom","age":"20"};
//        window.webkit.messagehandlers.jssendtooc.postmessage(dict);
//    }
//    </script>
    [usercontroller addscriptmessagehandler:self name:@"jssendtooc"];
    
    //初始化wkwebsitedatastore,并设置相关属性
    wkwebsitedatastore *datastore = [wkwebsitedatastore defaultdatastore];
//     如果为webview设置了这个data store,则不会有数据缓存被写入文件
//     当需要实现隐私浏览的时候,可使用这个
//    wkwebsitedatastore *datastore = [wkwebsitedatastore nonpersistentdatastore];
    
    //配置信息
    wkwebviewconfiguration *configuration = [[wkwebviewconfiguration alloc]init];
    configuration.preferences = preference;
    configuration.usercontentcontroller = usercontroller;
    configuration.websitedatastore = datastore;
    
    self.iwkwebview = [[wkwebview alloc]initwithframe:cgrectmake(0, 64, [uiscreen mainscreen].bounds.size.width, [uiscreen mainscreen].bounds.size.height-64) configuration:configuration];

    self.iwkwebview.navigationdelegate = self;
    self.iwkwebview.uidelegate = self;
    
    self.iwkwebview.allowsbackforwardnavigationgestures = yes;
    nsurl *url = [nsurl urlwithstring:@"https://www.baidu.com"];
    nsurlrequest *request = [nsurlrequest requestwithurl:url];
    [self.iwkwebview loadrequest:request];
    [self.view addsubview:self.iwkwebview];