質問: table.dequeueReusableCellWithIdentifier("Cell") as? CustomTableViewCell ・・・・ ``` という形で読み込んでいますが、スクロールしてセルを使いまわす際に前の画像やらが残っていて一瞬表示されます。スクロールをすばやく行うと非常に気持ち悪いです。 セルを使い回す際には初期化して使うなど行えないでしょうか?(通常どうやっているのでしょうか?)
回答: 同期的に値を更新している場合は`tableView(_:, cellForRowAtIndexPath:)`メソッドが必ず表示するより前に呼ばれるので、単純に値を上書きするだけでOKです。もちろん表示しているすべての値を書き換える必要があります。条件分岐などがあると、一部のラベルなどの更新を忘れることがよくあります。 おそらく問題は非同期的に画像などを取得していて、画像が読み込まれるよりも先にセルが表示されたときに、以前のデータが残ってしまっているような状況だと思います。 その場合も考え方は同様で、`tableView(_:, cellForRowAtIndexPath:)`で非同期の更新メソッドを呼ぶ前に、残っているデータをリセットします。リセットするデータに何を設定するかはアプリケーションによります。(デフォルト画像やローディング画像、あるいはnilなど) 非同期的にデータを取得している場合は、データが取得された時には、すでにセルがさらに再利用されて別のデータを表示するべきという場合があるので、その場合は取得したデータを表示しないように気をつける必要があります。(下の例では例えば画像のURLをセルに持たせて一致するかどうかを確認しています。) ``` func tableView(table: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = table.dequeueReusableCellWithIdentifier("Cell") as? CustomTableViewCell // 同期的に値をセットする場合は気にしなくてOK cell.textLabel.text = someText // 画像など非同期で取得されセットされる場合は関係ない // データが表示されないようにここでリセットする cell.imageView.image = defaultImage // デフォルト画像やnilなど、必要に応じてリセット cell.imageURL = "https://httpbin.org/image/png" Alamofire.request(.GET, "https://httpbin.org/image/png") .responseImage { response in if let image = response.result.value { // 取得するまでにさらに別のセルとして再利用されている可能性があるので // リクエストしたセルと一致するかどうか確認する if response.URL == cell.URL { cell.imageView.image = image } } } ```