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()
}
}
}
}
问题是:当我向下或向上滚动时,图像会重新加载,否则不会重新加载。只有 title
和 rating
会是
我只知道原因是这些行
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()
}
})
现在效果很好。
这是我的 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()
}
}
}
}
问题是:当我向下或向上滚动时,图像会重新加载,否则不会重新加载。只有 title
和 rating
会是
我只知道原因是这些行
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()
}
})
现在效果很好。