博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS-WKWebView的使用
阅读量:3964 次
发布时间:2019-05-24

本文共 11977 字,大约阅读时间需要 39 分钟。

参考文章:

 

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 
navigationDelegate;// UI代理@property (nullable, nonatomic, weak) id
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 
)scriptMessageHandler name:(NSString *)name;// 移除注入的协议, 在deinit方法中调用- (void)removeScriptMessageHandlerForName:(NSString *)name;// 通过WKUserScript注入需要执行的JavaScript代码- (void)addUserScript:(WKUserScript *)userScript;// 移除所有注入的JavaScript代码- (void)removeAllUserScripts;

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

JS调用OC:

简单理解就是:[userController addScriptMessageHandler:self name:@"JSSendToOC"];//userController是一个WKUserContentController对象,‘JSSendToOC’是方法名,

当JS端通过window.webkit.messageHandlers.JSSendToOC.postMessage()方法调用'JSSendToOC'方法时,我们可以通过下面的协议方法获取到JS端传过来的数据,做我们的操作。

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

 OC调用JS:

NSString *js = @"callJsFunction('hahaha')";   [self.webView evaluateJavaScript:js completionHandler:^(id _Nullable response, NSError * _Nullable error) {       NSLog(@"response:%@..error:%@",response,error);   }];

这里是调用了JS的‘callJsFunction’方法,这个方法名是随便起的。

 

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
*)allWebsiteDataTypes;// 查找指定类型的缓存数据// 回调的值是WKWebsiteDataRecord的集合- (void)fetchDataRecordsOfTypes:(NSSet
*)dataTypes completionHandler:(void (^)(NSArray
*))completionHandler;// 删除指定的纪录// 这里的参数是通过上面的方法查找到的WKWebsiteDataRecord实例获取的- (void)removeDataOfTypes:(NSSet
*)dataTypes forDataRecords:(NSArray
*)dataRecords completionHandler:(void (^)(void))completionHandler;// 删除某时间后修改的某类型的数据- (void)removeDataOfTypes:(NSSet
*)websiteDataTypes modifiedSince:(NSDate *)date completionHandler:(void (^)(void))completionHandler;// 保存的HTTP cookies@property (nonatomic, readonly) WKHTTPCookieStore *httpCookieStore

dataTypes:

// 硬盘缓存WKWebsiteDataTypeDiskCache,// HTML离线web应用程序缓存WKWebsiteDataTypeOfflineWebApplicationCache,// 内存缓存WKWebsiteDataTypeMemoryCache,// 本地缓存WKWebsiteDataTypeLocalStorage,// cookiesWKWebsiteDataTypeCookies,// HTML会话存储WKWebsiteDataTypeSessionStorage,//  IndexedDB 数据库WKWebsiteDataTypeIndexedDBDatabases,// WebSQL 数据库WKWebsiteDataTypeWebSQLDatabases

dataRecord:

// 展示名称, 通常是域名@property (nonatomic, readonly, copy) NSString *displayName;// 包含的数据类型@property (nonatomic, readonly, copy) NSSet
*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
* _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
* _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() 发送消息//        [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];

 

再加一个知识点:WKWebView加载的时候添加一个自定义的进度条。

此时我们需要获取到webview加载的进度数值。

这里可以通过添加监听来获取。

[self.iWKWebView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
estimatedProgress是WKWebView的一个属性。
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary
*)change context:(void *)context{ if ([keyPath isEqualToString:@"estimatedProgress"] && object==self.iWKWebView) { //获取到webview的进度数值,加载自定义的进度条 //self.iWKWebView.estimatedProgress } }

 

转载地址:http://qgkki.baihongyu.com/

你可能感兴趣的文章
偶然发现的面包屑
查看>>
CentOS 7 下挂载NTFS文件系统磁盘并设置开机自动挂载
查看>>
非插件实现Typecho语法高亮
查看>>
windows 下 netsh 实现 端口映射(端口转发)
查看>>
两个好用的命令行工具 watch 和 rsync
查看>>
信安入门神级书单
查看>>
【IPFS指南】IPFS的竞争对手们(一)
查看>>
docker更换国内镜像
查看>>
CentOS 下 tree命令用法详解
查看>>
docker上传镜像至Registry时https报错解决方法
查看>>
docker下删除none的images
查看>>
Linux提权获取敏感信息方法
查看>>
Ubuntu 16.04开机A start job is running for Raise network interface(5min 4s)解决方法
查看>>
Ubuntu 16.04开机隐藏菜单缩短时间
查看>>
《Linux内核设计与实现》- Linux的进程
查看>>
用户态切换到内核态的3种方式
查看>>
内核库函数
查看>>
Linux 系统内核空间与用户空间通信的实现与分析
查看>>
64位int类型用printf输出问题
查看>>
进程的状态转换
查看>>