GCWKWebViewJsBridgeはiOSのオリジナルとWKWebViewのインタラクションをより簡単にします

8241 ワード

プロジェクトではHybrid開発が多く使われ、nativeとjsのインタラクションにbridgeを作り、必要なものがあればダウンロードして直接使用することができます.Object-c言語を使用して、現在coapodsインポートをサポートしています.pod 'GCWKWebViewJSBridge', '~> 0.1.0'プロジェクトアドレスここをクリックして、役に立つ上のはstarにあげましょう
実装機能は次のとおりです.
  • Webコンソールへの印刷を実現した情報をxcodeコンソールで出力
  • //  xcode      web     
        [bridge registCaptureJSConsoleLog];
    

    トップページlog出力
    js console log:{
        details =     {
            dns = 33;
            onload = 634;
            ttfb = 1269;
        };
        display = 1522;
        lifecycle =     {
            "_1" =         {
                desc = "\U7f51\U9875\U91cd\U5b9a\U5411\U7684\U8017\U65f6";
                key = redirect;
                value = 0;
            };
            "_2" =         {
                desc = "\U68c0\U67e5\U672c\U5730\U7f13\U5b58\U7684\U8017\U65f6";
                key = cache;
                value = 14;
            };
            "_3" =         {
                desc = "DNS\U67e5\U8be2\U7684\U8017\U65f6";
                key = dns;
                value = 33;
            };
            "_4" =         {
                desc = "TCP\U8fde\U63a5\U7684\U8017\U65f6";
                key = tcp;
                value = 464;
            };
            "_5" =         {
                desc = "\U5ba2\U6237\U7aef\U53d1\U8d77\U8bf7\U6c42\U7684\U8017\U65f6";
                key = request;
                value = 755;
            };
            "_6" =         {
                desc = "\U670d\U52a1\U7aef\U54cd\U5e94\U7684\U8017\U65f6";
    
  • JS異常のキャプチャを実現し、コンソール
  • に出力
    [bridge registCaptureJSExceptionLog];
    

    ドメイン間の問題があり、Script error.しか収集できず、詳細は印刷できません.これはバグではありません.webkikソースがドメイン間問題があると判断した場合、安全のため、具体的なエラー情報は提供しません.
    bool ScriptExecutionContext::sanitizeScriptError(String& errorMessage, int& lineNumber, String& sourceURL)
        {
            KURL targetURL = completeURL(sourceURL);
            if (securityOrigin()->canRequest(targetURL))
                return false;
            errorMessage = "Script error.";
            sourceURL = String();
            lineNumber = 0;
            return true;
        }
    

    OCに対してJS関数を呼び出す場合、web側は実装されていません.この場合、エラーメッセージを次のように印刷できます.
    js exception Message: ReferenceError: Can't find variable: 
    ocCallJS1 - URL: https://www.jianshu.com/ - Line: 1 - Column:
     10 - Error object: {"line":1,"column":10,"sourceURL":
    "https://www.jianshu.com/"}
    
  • URLブロックインタラクションは、blockに統一的にカプセル化してコールバックし、集中的に管理する.照合優先度に関する問題
  • 実際の開発でブロックURLに遭遇する可能性がある場合、URLはパラメータを渡す必要があります.この場合、完全に一致するURLは一致せず、kwを含むマッチングしかできません.blockはkeyURLと完全なパスを返し、完全なパスを処理することでパラメータを取得できます.
    実際にマッチングURLに遭遇したとき、複数にマッチングすることができます.このとき、私たちは完全にマッチングして、得点が最も高いです.一致した長さを積分計算し、積分が最も高い一致を返します.実際のマッチングではshare:123,share:12345,share#などが出現し,ブロックされたリンクがwww.share12345.com/?であれば,マッチングしたのはshare12345と算出され,リターン中に関連論理処理が行われる.
    マッチングルールは次のとおりです.ここではマッチングルールを1つの関数に配置し、ビジネスに基づいて拡張することができます.
    - (NSString *)_machRuleWithUrl:(NSString *)URL{
        NSString * matchedURL = @"";
        //    ,      
        NSInteger currentMatchKeyScore = 0;
        for (NSString * keyURL in self.interceptKeyURLArray) {
            if ([keyURL isEqualToString:URL]){
                //      ,    
                matchedURL = keyURL;
                currentMatchKeyScore = MaxMatchScore;
                break;
            }
            //        ,     keyURL      ,       keyURL
            if ([URL containsString:keyURL]) {
                //              
                NSInteger matchScore = keyURL.length;
                if (currentMatchKeyScore < matchScore) {
                    matchedURL = keyURL;
                    currentMatchKeyScore = matchScore;
                }
            }else continue;
        }
        return matchedURL;
    }
    
    //      www.baidu.com
        [bridge registInterceptURLKeys:@[@"share:123",@"share:12345",@"share://info#"] handler:^(NSString * _Nonnull keyURL, NSString * _Nonnull URL) {
            NSLog(@"%@====
    %@",keyURL,URL); }];
  • 変数を注入することによって、JSにパラメータを入力し、jsonオブジェクトと文字オブジェクトの入力をサポートする.たとえば、Webページをレンダリングする前に、ユーザーtokenなどを取得する必要があります
  • //oc JS      ,    h5    token,    
        NSDictionary * userInfo = @{@"uid":@"10086",@"name":@"    ",@"age":@"22",@"token":@"oidahnfjabfiabfuaojfbaiufbafo"};
        [bridge nativeUploadJSArguments:userInfo filedName:@"uoloadUser" inTime:WKUserScriptInjectionTimeAtDocumentStart];
    

    *注入関数方式によりJSにパラメータを入力
    //oc JS    ,    h5             , h5  
        NSArray * lists = @[@" 1",@" 2",@" 3",@" 4"];
        [bridge nativeUploadJSArguments:lists useMethod:@"getOCMessage" inTime:WKUserScriptInjectionTimeAtDocumentStart];
    
  • 登録JSはOCコールバックを呼び出し、messageNameによるコールバック論理区分
  •  //    JS  oc  
        [bridge registJSMethods:@[@"ocShare",@"getUserJson"] nativeHandler:^(NSString * _Nonnull messageName, id  _Nonnull messageBody) {
             NSLog(@"%@:%@",messageName,messageBody);
        }];
    
  • OC呼び出しJS関数を登録し、単一パラメータ
  • をサポートする
    if (button.tag == 1) {
            //app  js,      ,           
            [bridge nativeCallJSMethod:@"ocCallJS" arguments:@"app  JS  " completionHandler:^(id  _Nullable result, NSError * _Nullable error) {
                
            }];
        }else{
             //app  js,       ,   JS     
            [bridge nativeCallJSMethod:@"ocCallJS1" completionHandler:^(id  _Nullable result, NSError * _Nullable error) {
                
            } arguments:@"      ",@"  1  ",@"   ",@"uid10086",nil];
        }
    

    ヘッダファイル
    @interface GCWKWebViewJSBridge : NSObject
    + (instancetype)bridgeWithWKWebView:(WKWebView *)webView;
    //    JS  ,              ;    JS   OC         
    - (void)registCaptureJSExceptionLog;
    ///     web      
    - (void)registCaptureJSConsoleLog;
    - (void)registInterceptURLKeys:(NSArray *)keyUrls handler:(interceptURLHandler)handler;
    - (void)registInterceptURLKey:(NSString *)keyURL handler:(interceptURLHandler)handler;
    - (BOOL)webViewBridgeCanInterceptURL:(NSString *)URL;
    
    /// native H5  js  
    /// @param jsCode js        
    /// @param userScriptInjectionTime     
    - (void)registNativeUserScript:(NSString *)jsCode inTime:(WKUserScriptInjectionTime)userScriptInjectionTime;
    
    ///  JS        , JS  
    /// @param param     ,      ,  JSON  
    /// @param filedName     
    /// @param userScriptInjectionTime     
    ///     :    
    - (void)nativeUploadJSArguments:(id)param filedName:(NSString *)filedName inTime:(WKUserScriptInjectionTime)userScriptInjectionTime;
    
    ///  JS         , JS  native  
    /// @param param           ,  JSON  
    /// @param methodName  js     
    /// @param userScriptInjectionTime js    
    /**
         :
     Let x = window.【methodName()】
     x      
     */
    - (void)nativeUploadJSArguments:(id)param useMethod:(NSString *)methodName inTime:(WKUserScriptInjectionTime)userScriptInjectionTime;
    
    /// JS  native
    /// @param jsMethod js    
    /// @param nativehandler native     
    /**
         
     window.webkit.messageHandlers.【jsMethod】.postMessage(【    native   】)
     */
    - (void)registJSMethod:(NSString *)jsMethod nativeHandler:(handler)nativehandler;
    ///     
    - (void)registJSMethods:(NSArray *)jsMethods nativeHandler:(handler)nativehandler;
    /**
    native   JS  
    @param methodName JS   
    @param param  JS    ,       ,      ,  JSON  
    @param completionHandler JS  
    
      :
          method
    */
    - (void)nativeCallJSMethod:(NSString *)methodName arguments:(id)param completionHandler:(void (^)(id _Nullable result, NSError * _Nullable))completionHandler;
    /**
    native   JS  
    @param methodName JS   
    @param param  JS      ,         ,      JS     ,      ,  JSON  
    @param completionHandler JS  
      :
          method
    */
    - (void)nativeCallJSMethod:(NSString *)methodName completionHandler:(void (^)(id _Nullable result, NSError * _Nullable))completionHandler arguments:(NSString *)param, ...;
    
    - (void)removeAllUserScripts;
    - (void)removeScriptMessageHandlerForName:(NSString *)method;
    @end