iOSのUIWebViewでのjavascriptのwindow.open絡みの問題

やたら「の」が多くてジブリならヒット間違いなしのタイトル。(ジブリでタイトルに「の」が入ったものはヒットするとかしないとか)

使用したものはSwift3、Xcode8、iOS10.2です。

背景

あるサイトでログイン後に見られるリザルト(成績)ページをまとめるアプリを作ろうとしました。
認証とかは面倒そうだしよくわかってないので、UIWebViewでユーザーに普通にサイト上でログインしてもらい、リザルトページを表示してもらって、そのhtmlソースをプログラムで処理しまとめようと考えました。

しかし、ログインの際と、ログインした後リザルトページを表示する段階2つでつまづきました。

一つ目:ログイン時にhttp通信してるみたい

こっちはどうでもいい話です。
ログインするときになぜかhttp通信を一瞬しているようで、https通信しかさせてくれなくなった最近のiOSではそのページにログインできません。
新しいキー、NSAllowsArbitraryLoadsInWebContentは

WebView を利用してウェブコンテンツを表示している場合、その内容に関しては http での通信を許容するというものです。

 だそうです。
これでUIWebViewではログインできるようになったのですが、WKWebViewだとなぜかできませんでした。
今でもわかってません。

二つ目 :javascriptのwindow.openで新しいウィンドウに表示させているみたい

こっちがメイン。

WKWebViewdだと、リンクにtarget _blankgが指定されている場合、よくないことが起こるらしいですがUIWebViewだと大丈夫みたいです。
しかしどちらも、javascriptのwindow.openには対応していません。

そのサイトにログイン後、なぜかUIWebViewではリザルトページが開けません。押しても真っ白になって止まるだけでした。

実は使おうと思っていたサイトは、ログイン後、リザルトページへのリンクがただのリンクではなくて
 リザルト

のような、javascriptを実行させるものだったせいなのでした。
なお、ここで使われているdoSubmit関数は以下のように定義されていて、新しいウィンドウを開き、フォームで情報を送信します。このときフォームを送信した結果を、さっき開いた新しいウィンドウに送るようにしてあるみたいです。

var intRtnVal;
      function doSubmit ( strURL, strAuthGp, strAuth, strStatus, strWindow ) {
        intRtnVal=fncControlSubmit ( 10 );
        if ( intRtnVal == true ) {
          window.open ( '', strWindow, 'menubar=no,status=yes,scrollbars=yes,location=no,resizable=yes' );
          document.F01.url.value=strURL;
          document.F01.HID_P6.value=strAuthGp;
          document.F01.HID_P8.value=strAuth;
          document.F01.target='ap'
          document.F01.pageflag.value=1000;
          document.F01.status.value=strStatus;
          document.F01.target=strWindow;
          document.F01.submit();
        } else {
          alert ( 'ただいま処理中です。OKボタンを押して、しばらく待ってから再度メニューをクリックしてください。' );
        }
      }

このstrWindowとかいうのを’_self’にしてあげれば、一つしか画面が開けないUIWebViewでも開けるはず。

そこで、

    // ロード完了時に呼ばれる
    func webViewDidFinishLoad(_ webView: UIWebView) {
    //iframe使ってたりすると複数回呼ばれるのでisLoadingをチェック
        if !webView.isLoading {
            if webView.stringByEvaluatingJavaScript(from: "document.URL") == "(そのページのURL)"{
                        //doSubmit関数のオーバーライド。strWindowに何が指定されていようと_selfとして送信する
                        webView.stringByEvaluatingJavaScript(from: "function doSubmit ( strURL, strAuthGp, strAuth, strStatus, strWindow ) {strWindow='_self';intRtnVal=fncControlSubmit ( 10 );if ( intRtnVal == true ){window.open( '','_self','menubar=no,status=yes,scrollbars=yes,location=no,resizable=yes' );document.F01.url.value=strURL;document.F01.HID_P6.value=strAuthGp;document.F01.HID_P8.value=strAuth;document.F01.target='ap';document.F01.pageflag.value=1000;document.F01.status.value=strStatus;document.F01.target='_self';document.F01.submit();} else {alert ( 'ただいま処理中です。OKボタンを押して、しばらく待ってから再度メニューをクリックしてください。' );}}")
                
            }
        }
    }

みたいな風に、ロード完了時にjavascriptを実行して、doSubmit関数をオーバーライドします。(例ではwindow.openはそのままにしてありますが、消してもいいです)
swiftでは複数行にわたって文字列を書く方法がない(のか?)から、数行のjavascriptを無理やり一行にしてあります。
これで晴れてUIWebViewから、新しいウィンドウを開いて表示しようとするサイトも表示できるようになりました。

もっと良い解決方法もあるんじゃないかと思うのですけどね…。

コメント