Webviewで遭遇したいくつかの問題

5626 ワード

App内はサードパーティのアクティビティにアクセスし、アクティビティを再起動するたびに再ログインする必要があります。


一波の活動のブームに追いつくために、ぐずぐずしたトラフィック、app内に第三者の人気活動が接続され、ユーザーは活動に参加する前に先に登録する必要があり、本appのtokenで第三者アカウントの登録したtokenを交換し、app内にcookieを保存し、ユーザーの登録状態を保存する.
    //    cookie
 NSURL *cookieHost=[NSURL URLWithString:self.url];
 NSDictionary *token = [NSDictionary dictionaryWithObjectsAndKeys:@"access_token", NSHTTPCookieName,
                                    [User currentUser].accessToken, NSHTTPCookieValue,
                                    @"/", NSHTTPCookiePath,
                                    [cookieHost host], NSHTTPCookieDomain,
                                    nil];

しかし,アクティビティエントリはapp内でずっと保存されているため,ユーザはappに再アクセスするたびにアクティビティに参加するために再ログインする必要があることが分かった.このような製品はもちろん承知しない.その後、ユーザーが再ログインする必要があるのは、ユーザーが以前にログインして保存していたクッキーが失効し、appが殺されたときに設定したクッキーが空になったためであることが分かった.
調べてみると、Cookieの失効時間であるNSHTTPCookieExpiresを設定したり、ついでにAPIでNSHTTPCookieDiscard key値を見たりすることもできます.discardクッキーのマークと言って、discardされたくないことを示しています.
フィールド設定が2つ追加されました
    NSDate *expiresDate = [NSDate dateWithTimeIntervalSinceNow:3600*24];//1     
    token[NSHTTPCookieExpires] = expiresDate;
    [token removeObjectForKey:NSHTTPCookieDiscard];

うん、それからずっと再ログインする必要はありません.

Webviewがロードしたurlパスに「#」の番号が付いています


もともと1つの問題に出会ったのは、社長が微信のある公衆番号からの技術帖を共有し、経路の末尾に2つの「##」号があり、会社のappのIMに共有し、クリックしてwebviewページでリンクを開くと、エラーが報告されるが、微信の内部で見ると問題ない.その後、urlを開く前にurlコードに対して、
[NSURL URLWithString:[self.url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]

このとき経路の「井井」号は「%23%23」と符号化され、符号化されたurlを使用して正常に開くことができる.しかし、すべてのurlが符号化されると、SPA(フロントエンドフレームワーク)フレームワークの下に配置されたページの中には、パスの後ろに井戸番号が付いていて、urlを符号化することはできません.そうしないと、パスが認識されません.その後、H 5の同僚に相談すると、一般的なページのフレームワークの下で経路に2つの連続井戸番号が現れることはめったにありません.その後、urlに現れた連続井戸番号を話して、1つの井戸番号に置き換えると、微信内のリンクが正常に開くことができ、以前に現れた多くの局外urlをテストしましたが、異常は見つかりませんでした.頼りない解決策のように見えますが...
 //webview  URL    # ,     ,  n  #      # 
    NSString *regExpStr = @"#+";
    NSString *replacement = @"#";
    NSRegularExpression *regExp = [[NSRegularExpression alloc]initWithPattern:regExpStr options:NSRegularExpressionCaseInsensitive error:nil];
    url = [regExp stringByReplacingMatchesInString:url options:NSMatchingProgress range:NSMakeRange(0, url.length) withTemplate:replacement];

webview error code


Webviewでは、ロード中に奇妙なエラーが報告され、エラーが発生した後、ビジネスニーズに応じてエラーページが表示されます.テストが入ってきて、私のこのページは开けることができるのに、私达のappはどうして开けないで、间违ったページを展示します...うん、私の鍋!デバッグでwebviewが間違っていることに気づきました.
  • 同じ2つのリクエストを同時に受信すると、webviewは自動的にcancleの1つをcancleし、errorCode
  • を1つ-999投げ出す.
  • ページ内の要素またはプラグインビューがプラグインをロードすると、204のerrorCode
  • が投げ出される.
  • urlリンクにurl仕様に合致しない文字がある場合、101のerrorCode
  • が投げ出されます.
  • https証明書が不足しているのにhttpsプロトコルリンクをロードすると-1202のerrorCodeが投げ出されるので、以上の1,2は無視できます.失敗したコールバックで無視すればいいです.
  • - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
           if ([self isSpecialCancle:error.code]) {
            return;
        }
        [self addErrorPage];
    }
    
    - (BOOL)isSpecialCancle:(NSInteger)code {
        switch (code) {
            case -999:
                return YES;
                break;
            case -1003:
                return YES;
                break;
            case 204:
                return YES;//    
                break;
            default:
                return NO;
                break;
        }
    }
    

    問題3 url符号化に対して解決できる.問題4、解決策は1枚1枚で、NSURLConnectionエージェントをカスタマイズするだけで、エージェントの中で今回のリクエストを信頼すればいいが、http証明書を作成したり、専門機関のhttp証明書を買ったりするのが一番だ.
    [NSURLConnection connectionWithRequest:self.request delegate:self];
    
    - (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
        }
        [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    }
    

    Webview内jsはalert()関数を呼び出し、crash


    デバッグ中に、jsがalert()関数を複数回呼び出すと、8のシステム上でcrashが発生し、プリントスレッドスナップショット発見alert()関数はシステムプライベートapiを実現し、UIalertViewのプライベート関数を使用し、呼び出しスレッドはjsのスレッドであることが分かった.初歩的な判断はjsスレッドでUI操作を呼び出し,crashを引き起こす.
    従って解決策はjsのalert関数を原生法で上書きすることである.
        JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        
        //  js alert
        context[@"alert"] = ^(id msg){
            if ([msg isKindOfClass:[NSString class]]) {
                [UIAlertView alertViewWithTitle:(NSString*)msg message:nil cancelButtonTitle:@"  " otherButtonTitles:nil onDismiss:^(NSInteger buttonIndex) {
                } onCancel:^{
                }];
                
            }
        };
    

    Webview注入OCオブジェクトによるメモリリーク


    Hybrid機能を行う場合、H 5にOCオブジェクトを暴露し、プロトコルメソッドを暴露するため、JsContextにOCオブジェクトコードを注入するには、次のようにします.
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    context[JSSDK_NATIVENAME] = self;
    

    しかし、最初にhybridが規模やフレームワークを形成していなかった場合、私たちのwebController->webviewは強保有関係であり、webview->JSSoextはシステムが定めた強保有関係であり、このときcontext[JSDK_NATIVENAME]=self操作はJSSoextにwebControllerを強保有させ、ループリードを形成させ、メモリ漏れを招く.
    そこでwebviewHandleを導入する必要があります
    WebController->webview強持webview->JSCoext強持JSCoext->webviewHandle強持webviewHandle->webController(または他のModule)弱エージェント関係で循環参照を解除します.