IOS進級のWKWebView

10927 ワード

前言
Xcode 8がリリースされた後、コンパイラはIOS 7をサポートしなくなったため、多くのアプリケーションはIOS 10に適してからIOS 7に適していない.その中には多くの大手企業、網易ニュース、滴滴移動などが含まれている.そのため、当社のアプリケーションもIOS 7を淘汰するつもりです.
IOS 8にサポートされ、最初に変更するのは、元のWKWebViewUIWebViewに置き換えることです.WKWebViewには明らかなメリットがたくさんあります.
  • より多くのHTML 5をサポートする機能
  • 公式に発表された60 fpsまでのスクロールリフレッシュ率と内蔵ジェスチャー
  • はUIWebViewDelegateとUIWebViewを14種類と3つのプロトコルに分割し、以前は多くの不便な機能が実現されていた.文書
  • Safari同じJavaScriptエンジン
  • より少ないメモリ消費量
  • UIWebView
    UIWebView
    WKWebView
    WKWebView
    したがって、WkWebviewUIWebViewに置き換える必要がある.
    基本的な使い方
    WKWebViewにはdelegate,WKUIdelegate,WKNavigationDelegteの2つがあります.WKNavigationDelegateは主にいくつかのジャンプ、ロード処理操作を処理し、WKUIdelegateは主にJSスクリプト、確認ボックス、警告ボックスなどを処理する.そのため、WKNavigationDelegateはもっとよく使われています.
    一般的な方法:
    #pragma mark - lifeCircle
    - (void)viewDidLoad {
        [super viewDidLoad];
        webView = [[WKWebView alloc]init];
        [self.view addSubview:webView];
        [webView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.view);
            make.right.equalTo(self.view);
            make.top.equalTo(self.view);
            make.bottom.equalTo(self.view);
        }];
        webView.UIDelegate = self;
        webView.navigationDelegate = self;
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
    
    }#pragma mark - WKNavigationDelegate//          
    - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
    
    }//           
    - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
    
    }//           
    - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    
    }//          
    - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation{
    
    }//               
    - (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
    
    }//       ,      
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{    NSLog(@"%@",navigationResponse.response.URL.absoluteString);    //    
        decisionHandler(WKNavigationResponsePolicyAllow);    //         //decisionHandler(WKNavigationResponsePolicyCancel);
    }//        ,      
    - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{     NSLog(@"%@",navigationAction.request.URL.absoluteString);    //    
        decisionHandler(WKNavigationActionPolicyAllow);    //         //decisionHandler(WKNavigationActionPolicyCancel);
    }#pragma mark - WKUIDelegate//       WebView
    - (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{    return [[WKWebView alloc]init];
    }//    
    - (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
        completionHandler(@"http");
    }//    
    - (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
        completionHandler(YES);
    }//    
    - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{    NSLog(@"%@",message);
        completionHandler();
    }

    OCとJSのインタラクション
    WKWebviewは、JavaScriptCoreまたはwebJavaScriptBridgeを使用することなく、jsインタラクションを実現するAPIを提供します.WKUSerContentControlを使用してjs nativeインタラクションを実現します.簡単に言えば、約束した方法を登録してから呼び出します.
    JS呼び出しOCメソッド
    ocコード(エラーがあり、メモリが解放されません):
    @interface ViewController (){
        WKWebView * webView;
        WKUserContentController* userContentController;
    }@end@implementation ViewController#pragma mark - lifeCircle
    - (void)viewDidLoad {
        [super viewDidLoad];    //    
        WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
        userContentController =[[WKUserContentController alloc]init];
        configuration.userContentController = userContentController;
        webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration];    //    
        [userContentController addScriptMessageHandler:self  name:@"sayhello"];//    name sayhello js  
    
        [self.view addSubview:webView];
        [webView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.view);
            make.right.equalTo(self.view);
            make.top.equalTo(self.view);
            make.bottom.equalTo(self.view);
        }];
        webView.UIDelegate = self;
        webView.navigationDelegate = self;
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
    }
    - (void)dealloc{    //      ,           remove 。
        [userContentController removeScriptMessageHandlerForName:@"sayhello"];
    }#pragma mark - WKScriptMessageHandler
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    NSLog(@"name:%@\\\
     body:%@\\\
     frameInfo:%@\\\
    ",message.name,message.body,message.frameInfo); }@end

    上のOCコードは認証テストをするとdeallocが実行されないことがわかります.これはだめです.メモリが漏洩します.なぜなら、[userContentController addScriptMessageHandler:self name:@"sayhello"];というコードがメモリを解放できないためです.(ps:weakポインタを使ってみても解放できないのは、どういうわけか分かりません.)そのため、正確な書き方は新しいcontrollerで処理され、新しいcontrollerはdelegateで巻き戻されるようにさらに改善する必要があります.
    ocコード(正しい書き方):
    @interface ViewController (){
        WKWebView * webView;
        WKUserContentController* userContentController;
    }@end@implementation ViewController#pragma mark - lifeCircle
    - (void)viewDidLoad {
        [super viewDidLoad];    //    
        WKWebViewConfiguration * configuration = [[WKWebViewConfiguration alloc]init];
        userContentController =[[WKUserContentController alloc]init];
        configuration.userContentController = userContentController;
        webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, 0, 100, 100) configuration:configuration];    //    
        WKDelegateController * delegateController = [[WKDelegateController alloc]init];
        delegateController.delegate = self;
    
        [userContentController addScriptMessageHandler:delegateController  name:@"sayhello"];
    
        [self.view addSubview:webView];
        [webView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.equalTo(self.view);
            make.right.equalTo(self.view);
            make.top.equalTo(self.view);
            make.bottom.equalTo(self.view);
        }];
        webView.UIDelegate = self;
        webView.navigationDelegate = self;
        [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.test.com"]]];
    }
    - (void)dealloc{    //      ,           remove 。
        [userContentController removeScriptMessageHandlerForName:@"sayhello"];
    }#pragma mark - WKScriptMessageHandler
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    NSLog(@"name:%@\\\
     body:%@\\\
     frameInfo:%@\\\
    ",message.name,message.body,message.frameInfo); }@end

    WKdelegateControllerコード:
    #import #import @protocol WKDelegate 
    
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;@end@interface WKDelegateController : UIViewController @property (weak , nonatomic) id delegate;@end

    .mコード:
    #import "WKDelegateController.h"@interface WKDelegateController ()@end@implementation WKDelegateController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    
    - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    if ([self.delegate respondsToSelector:@selector(userContentController:didReceiveScriptMessage:)]) {
            [self.delegate userContentController:userContentController didReceiveScriptMessage:message];
        }
    }@end

    h 5コード:
        function say()
    {//      window.webkit.messageHandlers.      .postMessage({body:     }   native        window.webkit.messageHandlers.sayhello.postMessage({body: 'hello world!'});
    }            

    hello world

                

    印刷されたロゴ:
     name:sayhello
     body:{
        body = "hello world!";
    }
     frameInfo: { URL: http://www.test.com/ }>

    注意点
  • addScriptMessageHandlerremoveScriptMessageHandlerForNameと組み合わせて発生しなければならない.そうしないと、メモリの漏れを引き起こす.
  • h 5は1つのパラメータしか伝達できません.複数のパラメータが必要な場合は辞書またはjsonで組み立てる必要があります.

  • oc呼び出しJSメソッド
    コードは次のとおりです.
    - (void)webView:(WKWebView *)tmpWebView didFinishNavigation:(WKNavigation *)navigation{    //say() JS   ,completionHandler     block
        [webView evaluateJavaScript:@"say()" completionHandler:^(id _Nullable result, NSError * _Nullable error) {        NSLog(@"%@",result);
        }];
    
    }

    h 5コードは上です.
    WebViewJavascriptBridge
    一般的に、良いUIには、良いサードパーティ製のパッケージフレームワークが開発されます.WebViewJavascriptBridgeの著者も、WKWebViewとJSのインタラクションをサポートするサードパーティフレームワーク:WKWebViewJavascriptBridgeを作成しました.
  • cocoaPods: pod 'WebViewJavascriptBridge', '~> 5.0.5'
  • githubアドレス:https://github.com/marcuswestin/WebViewJavascriptBridge

  • 主な方法は次のとおりです.
    //     
    + (instancetype)bridgeForWebView:(WKWebView*)webView;
    + (void)enableLogging;//     
    - (void)registerHandler:(NSString*)handlerName handler:(WVJBHandler)handler;//     
    - (void)callHandler:(NSString*)handlerName;
    - (void)callHandler:(NSString*)handlerName data:(id)data;
    - (void)callHandler:(NSString*)handlerName data:(id)data responseCallback:(WVJBResponseCallback)responseCallback;//  
    - (void)reset;//  WKNavigationDelegate
    - (void)setWebViewDelegate:(id)webViewDelegate;

    基本的な実現方法と上に書いたものの差は多くありませんが、パッケージして、興味のある子供靴は自分でpodして使うことができます.
    文/o転がる牛の赤ちゃんo(簡書作者)原文リンク:http://www.jianshu.com/p/4fa8c4eb1316著作権は作者の所有で、転載は作者に連絡して授権を得て、そして“簡書の作者”を表示してください.
    私は何百回もコードを虐待して、コードは私を初恋のように扱っています!