NSOperation 用于将图像加载到 TableView

NSOperation for loading image to TableView

这是我的 Movie class:

import UIKit

class Movie {
    var title: String = ""
    var rating: Double = 0
    var image: UIImage = UIImage()
}

我想加载movie的数组到tableView,我试过这样:

import UIKit
import Cosmos
import Alamofire
//import AlamofireImage
import SwiftyJSON

class Downloader {
    class func downloadImageWithURL(url:String) -> UIImage! {
        let data = NSData(contentsOfURL: NSURL(string: url)!)
        return UIImage(data: data!)
    }
}

class MovieViewController: UIViewController, UITableViewDataSource {

    @IBOutlet var tableView: UITableView!
    var movies: [Movie] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        fetchMovies()
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MovieTableViewCell
        let movie = movies[indexPath.row]
        cell.movieTitleLabel.text = movie.title
        cell.movieRatingView.rating = Double(movie.rating / 20)
        cell.movieImageView.image = movie.image
        return cell
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return movies.count
    }

    func fetchMovies() {
        let movieURLString = "https://coderschool-movies.herokuapp.com/movies?api_key=xja087zcvxljadsflh214"

        Alamofire.request(.GET, movieURLString).responseJSON { response in

            let json = JSON(response.result.value!)
            let movies = json["movies"].arrayValue
            let queue = NSOperationQueue()
            for movie in movies {
                let title = movie["title"].string
                let rating = movie["ratings"]["audience_score"].double
                let imageURLString = movie["posters"]["thumbnail"].string

                let movie = Movie()
                movie.title = title!
                movie.rating = rating!

                let operation = NSBlockOperation(block: {
                    movie.image = Downloader.downloadImageWithURL(imageURLString!)
                })
                queue.addOperation(operation)

                self.movies.append(movie)
                self.tableView.reloadData()

            }
        }
    }
}

问题是:当我向下或向上滚动时,图像会重新加载,否则不会重新加载。只有 titlerating 会是

我只知道原因是这些行

self.movies.append(movie)
self.tableView.reloadData()

之前编译
let operation = NSBlockOperation(block: {
     movie.image = Downloader.downloadImageWithURL(imageURLString!)
})
queue.addOperation(operation)

但是如果我向下滚动,它会像这样:

我已经用 AlamofireImage 完美地做到了,但我真的想用 NSOperation 来潜水。

我认为你应该确保 reloadData() 在主线程上。默认情况下,它发生在后台线程上,无法更新 UI.

dispatch_async(dispatch_get_main_queue(),{
   self.tableView.reloadData()
})

我通过将 reloadData 放到主线程来解决问题,如下所示:

let operation = NSBlockOperation(block: {
                    movie.image = Downloader.downloadImageWithURL(imageURLString!)
                    NSOperationQueue.mainQueue().addOperationWithBlock() {
                        self.tableView.reloadData()
                    }
                })

现在效果很好。