

Xcode 7.3を使ってSwiftプログラミングを行っています。

[code]

    func tableView(table: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = table.dequeueReusableCellWithIdentifier("Cell") as? CustomTableViewCell
    
            let url: NSURL = NSURL(string: (fileArray[indexPath.row] as? String)!+".jpg")!
            let req = NSURLRequest(URL:url)
            NSURLConnection.sendAsynchronousRequest(req, queue:NSOperationQueue.mainQueue()){(res, data, err) in
                let img = UIImage(data:data!)
                cell!.thumb.image = img
            }
    
[/code]

のようにしてセルの中に画像(cell.thumb.image)を表示しているのですが、高速にスクロールさせた場合、画像の読み込み及び表示が追いつかなく、停止した際にサムネイルがパタパタと切り替わります。

表示の必要がない画像（過ぎ去った）は読み込み、または表示をキャンセルすることはできないでしょうか？


CC BY-SA 3.0
2016-08-16T14:46:59.157
28321
2016-08-16T16:56:44.710
2016-08-16T16:45:29.973
5519
8593
question
swift uitableview
UITableview中のcell描画の中で必要なくなった画像表示をキャンセルするには


`NSURLConnection.sendAsynchronousRequest()`はキャンセル処理をサポートしていません。`NSURLConnection`はキャンセル可能なAPIも備えていますが、NSURLConnectionの使用はiOS
9から非推奨になっているので、代わりの新しいAPIである`NSURLSession`または`NSURLSession`を利用したライブラリ（Alamofireなど）を利用しましょう。

画像のダウンロードですので、`NSURLSession`から`NSURLSessionDataTask`を作成します。後ほど、セルが非表示（画面外）になった際にはキャンセルできるように、`NSURLSessionDataTask`は保持しておきます。

下記の例では`downloadTasksPerURL`というディクショナリを用いてURLをキーにして保持することにします。  
また、セルが非表示になった際にキャンセルするために`NSURLSessionDataTask`を特定できるように、セルに画像のURLを持たせるようにしています。

セルが画面外に出る際には、`tableView(_:didEndDisplayingCell:forRowAtIndexPath:)`というデリゲートメソッドが呼ばれますので、そのタイミングで該当の`NSURLSessionDataTask`を`cancel()`メソッドでキャンセルします。

下記はコードの例です。

[code]

    ...
    var downloadTasksPerURL = [NSURL: NSURLSessionTask]()
    ...
    
    func tableView(table: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        ...
        let imageURL = ...
    
        let task = NSURLSession.sharedSession().dataTaskWithRequest(NSURLRequest(URL: imageURL)) { (data, response, error) -> Void in
            if let error = error {
                return
            }
    
            dispatch_async(dispatch_get_main_queue()) {
                let image = UIImage(data: data!)!
                cell!.thumb.image = image
            }
        }
    
        cell.imageURL = imageURL
        downloadTasksPerURL[imageURL] = task
    
        task.resume()
    
        return cell
    }
    
    func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
        if let task = downloadTasksPerURL[cell.imageURL] {
            task.cancel()
        }
    }
    
[/code]


CC BY-SA 3.0
2016-08-16T16:56:44.710
28322
2016-08-16T16:56:44.710
5519
28321
answer