2017-03-03 10 views
2

UIWebViewの内部にWebページをロードする必要があるアプリケーション(swift)で作業しています。そのUIWebViewには<img src="http://www.example.com/uploads/43454.jpg" />要素があります。<img>タグソースをローカル(キャッシュされた)ソースに置き換えます。

このシナリオではすべて正常に動作しますが、問題は43454.jpgイメージが毎回5〜10メガバイトになる可能性があることです。したがって、UIWebViewが読み込まれると、イメージを約2分間ロードし続けます。さらに、この<img>タグはランダムなソース、すなわち22234.jpg,98734.jpg,33123.jpgなどを持つことができます。 aplicationので我々は、のUIWebViewに表示ダウンロードしてキャッシュするために必要なすべての可能な画像(この目的のためにカワセミライブラリを使用)

  1. 一覧:だから私は、次のアプローチを使用しようとしていますこのような状況に対処する

    起動。

  2. 私のUIWebViewが最初にURLを読み込んだとき、それには何もありません<img>要素src属性ですが、data-image-name="22234.jpg"属性 - 値のペアがあります。

  3. これでUIWebViewのコンテンツの読み込みが完了したら、data-image-name属性からイメージ名の値を取得します。

  4. キャッシュ内のそのイメージを確認し、<img>要素のsrc属性をキャッシュからそのイメージで更新します。

このようにして、UIWebViewはイメージを何度も何度もダウンロードすることはありません。

注:UIWebViewが自動的にリソースキャッシュを管理すると仮定します。他のすべてのファイルタイプ*.js,*.cssは適切にキャッシュされており、繰り返し読み込まれることはありません。同じものは画像のために行っていない、理由を知らない。

このアプローチが大丈夫だとすれば、どのように達成するべきですか(Swift 2.2)?

すばらしいヘルプがあれば幸いです。ありがとう

+1

私の最初の賭けは、サーバー側にキャッシュコントロールを持つものがあることでしょう。デスクトップブラウザーでサイトを開き、まずサーバーがイメージのために返すヘッダーを表示することができますか?['Cache-Control'](https://developer.mozilla.org/en-US/docs/Web/HTTP /ヘッダー/キャッシュコントロール)?現代のブラウザの「開発ツール」で行うことができます。キャッシュされているJSファイルとCSSファイルでヘッダーを比較することもできます。また、質問にヘッダを追加するのに役立つかもしれません。 – SergGr

+0

その作業を行うのが難しいようです。基本的にUIWebViewとネットワークの間に独自のキャッシュを挿入する必要があります。私の直感はそれが不可能だということです。 iOSがサポートしているものではありません。ページをネイティブのiOSビューに翻訳できますか?そうであれば、画像の読み込みをより詳細に制御できます。 –

+0

@SergGrに言及しているように、UIWebViewにはキャッシングが組み込まれていますが、高度なレベルでは再実装する可能性があります。 jpgのヘッダーがキャッシングを無効にしていないことを確認してください。このキャッシュをプライミングしたい場合は、起動時にこれらのイメージを使ってWebViewをオフスクリーンにしてロードすることができます。 – dmorrow

答えて

1

に内蔵されているHTML文字列をロードするように見えるのUIWebViewを伝えるこれが私のプロジェクトの一つで同じ状況のようです。私はまったく同じシナリオを持っていました。私はここに自分のコードを貼り付けるつもりです、あなたのソリューションを理解するのに役立つかもしれません。

とすぐに私のアプリの負荷が私は画像のURLの配列を作成し、(ディスクに)すべての画像をダウンロードしてキャッシュすること Kingfisherライブラリにそれを渡すよう
  1. 。私が最初に自分のWebビューをロードし、その後、キャッシュ内の特定の画像を確認するために、次のコードを使用し、見つかった場合はbase64文字列にそれを変換してのsrc属性にそれを戻す私のWebビュー画面で

    for url in response { 
        let URL = NSURL(string: url as! String)! 
        self.PlanImagesArray.append(URL) 
    } 
    
    let prefetcher = ImagePrefetcher(
    urls: self.PlanImagesArray, 
    optionsInfo: nil, 
    progressBlock: { 
        (skippedResources, failedResources, completedResources) ->() in 
         print("progress resources are prefetched: \(completedResources)") 
         print("progress resources are failedResources: \(failedResources)") 
         print("progress resources are skippedResources: \(skippedResources)") 
          }, 
    completionHandler: { 
        (skippedResources, failedResources, completedResources) ->() in 
         print("These resources are prefetched: \(completedResources)") 
         print("These resources are failedResources: \(failedResources)") 
         print("These resources are skippedResources: \(skippedResources)") 
    
         self.activityLoadingIndicator.stopAnimating() 
    }) 
    
    prefetcher.start() 
    
  2. 素子。

    func webViewDidFinishLoad(webView : UIWebView) { 
        //UIApplication.sharedApplication().networkActivityIndicatorVisible = false 
        print("webViewDidFinishLoad") 
    
        let xlinkHref = webView.stringByEvaluatingJavaScriptFromString("document.getElementById('background_image').getAttribute('xlink:href')") 
    
        //print("xlink:href before = \(webView.stringByEvaluatingJavaScriptFromString("document.getElementById('background_image').getAttribute('xlink:href')"))") 
    
        if xlinkHref == "" { 
    
         let imageCacheKey = webView.stringByEvaluatingJavaScriptFromString("document.getElementById('background_image').getAttribute('data-cache-key')") 
         let imageCachePath = ImageCache.defaultCache.cachePathForKey(imageCacheKey! as String) 
         var strBase64:String = "" 
    
         webView.stringByEvaluatingJavaScriptFromString(
          "var script = document.createElement('script');" + 
          "script.type = 'text/javascript';" + 
          "script.text = \"function setAttributeOnFly(elemName, attName, attValue) { " + 
          "document.getElementById(elemName).setAttribute(attName, attValue);" + 
          "}\";" + 
          "document.getElementsByTagName('head')[0].appendChild(script);" 
         )! 
    
         if(imageCachePath != "") { 
    
          ImageCache.defaultCache.retrieveImageForKey(imageCacheKey! as String, options: nil) { (imageCacheObject, imageCacheType) ->() in 
    
          let imageData:NSData = UIImageJPEGRepresentation(imageCacheObject!, 100)! 
          strBase64 = "data:image/jpg;base64," + imageData.base64EncodedStringWithOptions(.EncodingEndLineWithCarriageReturn) 
          webView.stringByEvaluatingJavaScriptFromString("setAttributeOnFly('background_image', 'xlink:href', '\(strBase64)');")!  
         } 
    
        } else { 
    
         webView.stringByEvaluatingJavaScriptFromString("setAttributeOnFly('background_image', 'xlink:href', '\(imageCacheKey)');")! 
    
        } 
    
    } 
    

それがお役に立てば幸いです。

+0

これは有望なようです。それを試していませんでした。テストドライブを与えた後、ここに戻ります。おかげで@カディール – Ali

+0

ビンゴ..!それでおしまい。これは魅力のように働いた。あなたの回避策はトリックでした。特にbase64エンコーディング部分。それを愛して:) – Ali

+0

@Aliありがとう。私は恩恵を受けたとは想像もできません;)これがうまくいったのを聞いてうれしいです。 –

0

私は基本的に言っているように聞こえる "私は画像が前もって何かを知っているので、私はUIWebViewが毎回サーバーからそれらを読み込むのを待っていません。私のローカルコピーを代わりに使用します。

それはハックですが、私が最初に考えました。一つは、ユーザーに表示され、他方が隠されている:

  1. 2 UIWebViewsを持っています。
  2. 非表示のUIWebViewの実際のページを「トリガ」します。 HTMLがあなたに届くと...
  3. 新しい文字列を作成します。これは、そのHTMLのコピーですが、<img src="http://...と置き換えられ、<img src=\"file://...と置き換えられ、ディスク上の正しいイメージを指し示すイメージタグを持ちます。
  4. は今、あなたは、ステップ3
+0

キャッシュはどうですか?私はちょうど画像の読み込み時間を短縮したい。私はすべての画像がアプリケーションの最初の時点でキャッシュにロード/ダウンロードされるようにする(ログイン画面)。そして、ダウンロードした画像の1つが表示される特定のWebビューに移動する。私がそこに着くと、私のアプリは、このWebビューが表示する必要がある画像(要素の "data-key"属性から決定される)を決定し、その画像をキャッシュでチェックする必要があります。 – Ali

+0

キャッシュ内にすでに存在する場合は、それを取り出して要素の「src」属性に入れます。キャッシュに見つからない場合は、そのイメージの正確なURLを「src」属性に入れてダウンロードします。 – Ali

+0

あなたの答えでは、画像ダウンロード時間(隠されたUIWebView)は効果がないようです(実際のダウンロード時間がかかります)。だからポイントは同じです。画像のダウンロード時間を短縮するにはどうすればよいですか? – Ali

関連する問題