2016-03-31 6 views
7

TinderのようなUICollectionViewに「フルスクリーンカード」を表示するアプリを開発しました。カードには画像とテキストが含まれています。 UICollectionViewのセルにSDWebImagesd_setImageWithURLメソッドを使用してイメージをロードしていました。iOSで画像をプレロードする

しかし、ユーザーがカードに乗っているときに画像がほとんど読み込まれたため、これは私に良いパフォーマンスを与えていませんでした。従って私は次のようにこれを行うにはSDWebImagePrefetcherプリフェッチ・キューを使用: -

func startImagePreloadingOperationForIndex(index:Int) 
{ 
    let numberOfImagesToBePreloadedOnEachSide = 20 
    var previousIndex = index - numberOfImagesToBePreloadedOnEachSide 
    var nextIndex = index + numberOfImagesToBePreloadedOnEachSide 

    if previousIndex < 0 
    { 
     previousIndex = 0 
    } 
    if nextIndex >= currentNewsCollection.count 
    { 
     nextIndex = currentNewsCollection.count - 1 
    } 

    if previousIndex >= nextIndex || currentNewsCollection.isEmpty 
    { 
     return 
    } 
    let arrayOfNewsStories = currentNewsCollection[previousIndex...nextIndex] 

    let arrayOfImageURLs = arrayOfNewsStories.map({ ImageUtility.getImageStringForNewsStory($0) }) 

    SDWebImagePrefetcher.sharedImagePrefetcher().prefetchURLs(arrayOfImageURLs, progress: { (x, y) -> Void in 
     }) { (x, y) -> Void in 
    } 
} 

ユーザーが特定のカードの上に着地するときに、この関数が呼び出されます。先読みキューは自動的にキャッシュ内のイメージをダウンロードしないように管理しますので、私はそれについて心配する必要はありません。これに加えて、のcellForItemAtIndexPathを使用して、ダウンロードしたイメージをキャッシュから取得します。

これは、ユーザーがカードにいるときにイメージをプリロードするので、これはより良い解決策です。しかし、これは並列キューです。画像Noを意味します。インデックス+20は、現在の画像とユーザが画像を待たなければならない前にロードすることができる。また、ユーザーが50枚以上のカードをスクロールしてメモリ使用量が増加し続けると、アプリが少し遅くなる。

これ以上の改善点はありますか?

おかげ

答えて

1

私は、ディスクからそれらをロードし、その後、ディスクに画像を保存し、独自のキューを処理することをお勧めしたいです。代わりに、並列キューの

、シリアルキューを使用するか、または少なくとも並列接続数

+0

マイケルに感謝します。 SDWebImageは最適化されたキューを提供するので、自分のキューを追加することでどのように問題が解決されるのでしょうか。私はシリアルキューを使用しようとしましたが、それは遅すぎることが判明していました。私はまた、ロードされている画像の数で遊んでみたが、それは助けていなかった –

5

sd_setImageWithURLと現在のカードの画像をダウンロードして、完了ハンドラ内でプリフェッチキューのダウンロードを開始を断ります。このようにして、現在の画像は常に最高の優先順位を持ち、遅れることはありません。

currentCardImageView.sd_setImageWithURL(url) { (image, error, imageCacheType, url) in 
    // start prefetching here 
} 

現在のイメージがすでにダウンロードされている場合、SDWebImageはこれを認識してキャッシュからフェッチします。

遅延の他の問題とメモリ消費量は、プリフェッチされたイメージの数を減らすことで解決できる可能性があります。 20はかなり高いですが、5で十分でしょうが、これは画像サイズ、ネットワーク速度などによって異なります。 1で始まり、テストし、2に増やし、テストして、増やすなど。あなたがポイントを見つけるまで、それは遅れます。

+0

ありがとう@ダーコー。これは現在のイメージの問題を解決するだけでしょうか?私は5枚の画像しかプリフェッチしようとしませんでしたが、それはまたメモリと遅れの問題を引き起こしていました。 –

+0

1つだけプリフェッチしてみてください。画像の大きさはどれくらいですか?そして、通常のネットワーク速度は何ですか? – Darko

+0

イメージのサイズは100KB未満で、予想されるネットワーク速度は3G/4G/Wi-Fiです –

1

私は開発しているAppに類似の問題を解決しました。私のアプリには何千ものユーザーがいて、それぞれにアバターがあるかもしれません。

パフォーマンスを向上させるために、私はアバター要求を管理する3レベルのコントローラーを開発しました。

まず、NSCache(最近使用されたすべてのアバターをNSCacheに保存します - これはiOSによって処理されるので、必要に応じてキャッシュメモリを解放することに気を付ける必要はありません)を確認します。 NSCacheを設定するには、いくつかのパラメータを定義するだけです。

アバターがNSCacheに見つからない場合は、最近使用したアバターがBlobフィールドとして保存されている自分のローカルDb(Sqlite)をチェックします。デバイスのメモリを節約するために古いデータを解放し、ローカルDbでクリーンアップを実行する必要があることを覚えておいてください。

まだ見つからない場合は、LIFOメソッド(先入れ先出し)を使用してキューに要求を保存します。つまり、ローカルユーザがユーザリストをスクロールしているときは、画面上の現在のユーザのアバタは、すでにテーブルビュー画面から外れているアバタの前に取得する必要があります。

もう一度、ユーザーが画面をすばやくスクロールしている間にパフォーマンスを再向上させる(選択を決める)ために、ダウンロードを要求しません。ユーザーがテーブルビューのスクロールを遅くするたびにダウンロードを開始するだけです。これを超えて、私はパラレルダウンロード数を制限します。ダウンロードスロットが開かれるたびに新しいダウンロードが開始されます(成功または失敗)。

これらの最適化は私のために非常にうまくいく、私のアプリケーションは軽い実行中です。

私はあなたを助けてくれることを願っています。

+0

ありがとうございます。私の解決策は2つのレベルの解決策のようです。 SDImageCacheはNSCacheに代わるもので、2番目のレベルとしてキューを実装しました。ここでSQLiteレイヤーを追加するとパフォーマンスが向上しますか? –

+0

こんにちはRajeev。私は、デバイスを再起動したり、アプリケーションを再起動したり、iOSがNSCacheからそれをリリースしたかどうかなど、SQLiteを追加しました。その場合、SQLiteなしでは、AppはWebサービス/ AWSから再び欠落したアバターをダウンロードする必要があります。これを避けるために、アバターが既にローカルdb(SQLite)上にある場合、Appはそれを再度ダウンロードする必要はありません。ローカルのdbからアバターを取得し、NSCacheを保存してAppに返します。 –

関連する問題