WKWebView兼容UIWebView

345 阅读2分钟

1.苹果邮件

ITMS-90809: Deprected API Usage - App updates that use UIWebView will no longer be accepted as of December 2020 Instead,use WKWebView for improved security and reliability.

2.UIWebView

2.1UIWebViewDelegate

1.webView:shouldStartLoadWithRequest:navigationType,加载webView之前,是否允许加载

2.webViewDidStartLoad: 开始加载网页

3.webViewDidFinishLoad: 网页加载完成

4.webView:didFailLoadWithError: 网页加载失败

3.WKWebView

3.1.WKNavigationDelegate

1. webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(**void** (^)(WKNavigationActionPolicy))decisionHandler请求开始前,会先调用此代理方法
2.webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation 开始导航时
3.webView:(WKWebView *)webView didFinishNavigation:(**null_unspecified** WKNavigation *)navigation 导航完成时
4.webView:(WKWebView *)webView didFailNavigation:(**null_unspecified** WKNavigation *)navigation withError:(NSError *)error 导航失败

3.2.WKUIDelegate

1. webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(**void** (^)(NSString * **_Nullable**))completionHandler 同步给js返回值可以使用JS的prompt进行返回

3.改造方案

3.1 JS脚本

1.自己编写一个js脚本,先定义一个对象jsCallNative(可随意写)
var jsCallNative = {};

2.把之前和前端协商的对象,jsCallNative去拿到该对象

window["ycfobj"] = jsCallNative;

3.用该对象去处理协商好的方法,h5是window.ycfobj.launchPay (launchPay是协商好的方法)

然后我们自己来接受该方法,并用window.webkit.messageHeadlers[对象方法].postMessage(),通过这样,我们定义的WKWebView就能监听到该方法。

/* 支付 payType: 支付方式 
 successCallback: 支付成功的js回调方法
 failureCallback: 支付失败的回调方法 
 orderNo:订单号 
 orderInfo: 支付所需的信息 
*/
jsCallNative.launchPay = function (payType, successCallback, failureCallback, orderNo, orderInfo) {
    var namespace = "launchPay";
    if (!window.webkit.messageHandlers[namespace]) return;
    var wrap = {
        "payType": payType,
        "successCallback": successCallback,
        "failureCallback": failureCallback,
        "orderNo": orderNo,
        "orderInfo": orderInfo,
    };    
window.webkit.messageHandlers[namespace].postMessage(wrap);}

4.前端js直接获取APP方法结果(需同步),例子想获取微信信息,可以通过prompt来返回结果。

jsCallNative.hasYcfWxInfo = function () {
    var result = window.prompt("hasYcfWxInfo");
    return result;
}

3.2 WKWebView处理脚本

1.通过WKWebViewConfiguration来添加一个脚本。

  NSString *wkjs = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"wkWebView" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
  WKUserScript *script = [[WKUserScript alloc] initWithSource:wkjs injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
 [config.userContentController addUserScript:script];

2.通过WKWebViewConfiguration监听对象

[config.userContentController addScriptMessageHandler:self name:name];

3.通过WKScriptMessageHandler处理方法

userContentController:(WKUserContentController *)userContentControllerdidReceiveScriptMessage:(WKScriptMessage *)message

4.通过evaluateJavaScript把数据传回给前端JS,successCallback是约定的方法

 NSString *js = [NSString stringWithFormat:@"successCallback(%@)","传回的数据"];
 [self.webView evaluateJavaScript:js completionHandler:^(id _Nullable object, NSError * _Nullable error) {
  }];

5.通过prompt来返回同步结果

 (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler{
    if ([prompt isEqualToString:@"hasYcfWxInfo"]) {
        completionHandler("返回结果");
        return;
    }
}