2016-09-12 13 views
1

セルの非同期イメージダウンロードを延期するのは安全ですか?この背後にあるアイデアは、URLSession.shared.image(...)のコールバック関数をセルの作成後に実行し、一度呼び出すcellForRow(at:indexPath)が有効であるようにしたいということです。このメソッドを延期することなくこの時点ではnilを返します。遅延を使用したUITableViewCellでのレイジーイメージのダウンロード

  • URLSession.shared.imageは、データのタスクを実行し、引数に与えたURLが有効である場合にのみ、エスケープコールバックを与え、画像が含まれているプラ​​イベートな拡張機能です。

  • setImage(image:animated)は、簡単なアニメーションを使用してUIImageViewで画像を設定できるプライベートな拡張です。

延期する方法がない場合は、別の方法を示してください。

フィードバックはありがたいです、ありがとうございます!

override func tableView(_ tableView: UITableView, cellForRowAt 
    indexPath: IndexPath) -> UITableViewCell { 

    let cell = baseCell as! MyCell 
    let datum = data[indexPath.row] 
    cell.imageView.setImage(placeholderImage, for: .normal) 

    defer { 
     URLSession.shared.image(with: datum.previewURL) { image, isCached in 
      if let cell = tableView.cellForRow(at: indexPath) as? MyCell { 
       cell.imageView.setImage(image, animated: !isCached) 
      } 
     } 
    } 

    return cell 
} 
+0

あなたはそれのためにSDWebImageサードパーティを試しますか? –

答えて

1

NSHipsterはどのように/延期、hereを使用するには良い記事を持っています。

私はこのような方法でdeferを使用しません。遅延の意図は、多くの出口点に分散させるのではなく、1ブロックのコード内のメモリをクリーンアップ/割り当て解除することです。

関数全体で複数のガードステートメントを使用し、その中のすべてのメモリを割り当て解除する必要があると考えてください。

これを使用して、事実の後にコードを追加するだけではなりません。

@jagveerで述べたように、SDWebImageキャッシュなど、既にこれを行う多くのサードパーティのライブラリがあります。 AFNetworkingとAlamoFireも同じものを内蔵しています。すでに完了しているときにホイールを再発明する必要はありません。

0

この場合、deferは有効ではありません。 deferは、スコープが終了したときに呼び出されるブロックを設定します。これはすぐに行います。

Dispatchを使用して、別のスレッドで実行するブロックのスケジュールを設定したいと思います。 UIを更新するには、メインスレッドに戻る必要があります。

これは後で発生する可能性があるため、セルが同じエントリに使用されており、ユーザーがさらにスクロールしたときに再利用されていないことを確認する必要があります。セルを再度フェッチすることは、最初の呼び出しを再度トリガするようになると再利用された場合はお勧めできません。私は通常、カスタムのUITableViewCellクラスにいくつかの識別子を追加してチェックします。

また、セルを作成せず、他の変数からセルをフェッチするだけです。これは、複数のセルがある場合、問題になる可能性があります。

override func tableView(_ tableView: UITableView, cellForRowAt 
indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "base") as! MyCell 
    cell.row = indexPath.row 
    let datum = data[indexPath.row] 
    cell.imageView.setImage(placeholderImage, for: .normal) 

    DispatchQueue.global().async { 
     // Runs in a background thread 
     URLSession.shared.image(with: datum.previewURL) { image, isCached in 
      DispatchQueue.main.async { 
       // Runs in the main thread; safe for updating the UI 
       // but check this cell is still being used for the same index path first! 
       if cell.row == indexPath.row { 
        cell.imageView.setImage(image, animated: !isCached) 
       } 
      } 
     } 
    } 

    return cell 
} 
関連する問題