前言
WKWebView是苹果在 iOS8.0以后推出的新的 webView库。目前现在很多 APP 都混合了 webView,这个库将来的用处会越来越大。这一段正好有个小项目用到了WKWebView ,学习了一下,在这里写篇文章总结一下。
WebKit Framework
iOS 中和 webView 相关和交互的文件都放到了 WebKit 这个库中
#import <WebKit/WKBackForwardList.h>
#import <WebKit/WKBackForwardListItem.h>
#import <WebKit/WKContentRuleList.h>
#import <WebKit/WKContentRuleListStore.h>
#import <WebKit/WKError.h>
#import <WebKit/WKFoundation.h>
#import <WebKit/WKFrameInfo.h>
#import <WebKit/WKHTTPCookieStore.h>
#import <WebKit/WKNavigation.h>
#import <WebKit/WKNavigationAction.h>
#import <WebKit/WKNavigationDelegate.h>
#import <WebKit/WKNavigationResponse.h>
#import <WebKit/WKOpenPanelParameters.h>
#import <WebKit/WKPreferences.h>
#import <WebKit/WKPreviewActionItem.h>
#import <WebKit/WKPreviewActionItemIdentifiers.h>
#import <WebKit/WKPreviewElementInfo.h>
#import <WebKit/WKProcessPool.h>
#import <WebKit/WKScriptMessage.h>
#import <WebKit/WKScriptMessageHandler.h>
#import <WebKit/WKSecurityOrigin.h>
#import <WebKit/WKUIDelegate.h>
#import <WebKit/WKURLSchemeHandler.h>
#import <WebKit/WKURLSchemeTask.h>
#import <WebKit/WKUserContentController.h>
#import <WebKit/WKUserScript.h>
#import <WebKit/WKWebView.h>
#import <WebKit/WKWebViewConfiguration.h>
#import <WebKit/WKWebsiteDataRecord.h>
#import <WebKit/WKWebsiteDataStore.h>
#import <WebKit/WKWindowFeatures.h>
#import <WebKit/WebKitLegacy.h>
上面是整个库的头文件。其中核心是WKWebView.h头文件。
WKWebView 注入js代码
WKWebView 执行js代码,是通过 WKUserContentController 和 WKUserScript两个类来实现
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"js"];
NSString *filejs = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
WKUserScript *userscript = [[WKUserScript alloc] initWithSource:filejsinjectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[wkUController addUserScript:userscript];
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
wkWebConfig.userContentController = wkUController;
self.webView = [[WKWebView alloc] initWithFrame:self.contentView.frame configuration:wkWebConfig];
首先创建WKUserScript对象,用来保存注入到 web View 的脚本。
一个脚本对应于一个 WKUserScript 对象
- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;
- source 对应于脚本的文本
- injectionTime 对应于脚本注入的时间 是个枚举值, WKUserScriptInjectionTimeAtDocumentStart,
WKUserScriptInjectionTimeAtDocumentEnd
-forMainFrameOnly 脚本注入的范围,Yes 表示为仅仅注入到主框架,NO 表示注入到所有的框架
第二步:创建WKUserContentController对象,WKUserContentController用来提供JavaScript 传递到 web view的方法。通过使用 - (void)addUserScript:(WKUserScript *)userScript 方法来增加脚本。
第三步 创建WKWebViewConfiguration 对象 这个对象用来收集初始化WKWebView 相关的属性信息。
他保有一个WKUserContentController类型的属性
@property (nonatomic, strong) WKUserContentController *userContentController;
第四步 初始化 WKWebView
self.webView = [[WKWebView alloc] initWithFrame:self.contentView.frame configuration:wkWebConfig];
WKWebView 执行 js 语句
- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;
WKWebView 通过这个语句来执行js语句,js语句执行的结果通过completionHandler block语句传递出来。
JS 传递数据 WKWebView
有时候需要在 JS 返回数据给 iOS APP,例如当点击一个条目的时候,希望把条目的信息传递给 iOS APP,可以
js 可以利用 window.webkit.messageHandlers..postMessage() 来进行传递数据。
例如
window.webkit.messageHandlers.appName.postMessage({body: '传数据'});
appName就是我们要注入的名称,注入以后,就可以在JS端调用了,传数据统一通过body传,可以是多种类型,只支持NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull类型。
// 注入JS对象名称AppModel,当JS通过appName来调用时,
// 我们可以在WKScriptMessageHandler代理中接收到
[config.userContentController addScriptMessageHandler:self name:@"appName"];
当JS通过appName发送数据到iOS端时,通过WKScriptMessageHandler 代理,就会收到数据
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController
didReceiveScriptMessage:(WKScriptMessage *)message {
if ([message.name isEqualToString:@"AppModel"]) {
// 打印所传过来的参数,只支持NSNumber, NSString, NSDate, NSArray,
// NSDictionary, and NSNull类型
NSLog(@"%@", message.body);
}
}