当前位置: 移动技术网 > IT编程>移动开发>IOS > iOS-WKWebView的使用

iOS-WKWebView的使用

2018年10月18日  | 移动技术网IT编程  | 我要评论

丽人保镖之马道疑云,汤灿年龄,喜爱夜猫

参考文章:

 

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:

#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];

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网