Swift:UIImages 在 table 视图中出现乱序
Swift: UIImages appearing out of order in table view
我正在从我的 Parse 后端查询图像,并在 UITableView
中按顺序显示它们。尽管我一次一个地下载和显示它们,但它们在我的 table 视图中显示完全乱序。每张图片(专辑封面)对应一首歌曲,所以我得到的每首歌曲的专辑封面都不正确。有人会如此好心地指出为什么他们看起来不正常吗?
class ProfileCell: UITableViewCell {
@IBOutlet weak var historyAlbum: UIImageView!
}
class ProfileViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var historyAlbums = [PFFile]()
var albumCovers = [UIImage]()
// An observer that reloads the tableView
var imageSet:Bool = false {
didSet {
if imageSet {
// Reload tableView on main thread
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) { // 1
dispatch_async(dispatch_get_main_queue()) { // 2
self.tableView.reloadData() // 3
}
}
}
}
}
// An observer for when each image has been downloaded and appended to the albumCovers array. This then calls the imageSet observer to reload tableView.
var dataLoaded:Bool = false {
didSet {
if dataLoaded {
let albumArt = historyAlbums.last!
albumArt.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data: imageData)
self.albumCovers.append(image!)
}
} else {
println(error)
}
self.imageSet = true
})
}
self.imageSet = false
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Queries Parse for each image
var query = PFQuery(className: "Songs")
query.whereKey("user", equalTo: PFUser.currentUser()!.email!)
query.orderByDescending("listenTime")
query.limit = 20
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
if let albumCover = object["albumCover"] as? PFFile {
// Appending each image to albumCover array to convert from PFFile to UIImage
self.historyAlbums.append(albumCover)
}
self.dataLoaded = true
}
}
} else {
println(error)
}
self.dataLoaded = false
})
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var profileCell = tableView.dequeueReusableCellWithIdentifier("ProfileCell", forIndexPath: indexPath) as! ProfileCell
profileCell.historyAlbum.image = albumCovers[indexPath.row]
return profileCell
}
}
}
你让它们乱序的原因是你正在为每个单独触发后台任务。
您可以在后台线程中一次性获得所有对象列表。那很好。然后,一旦你有了,你就调用一个方法(通过 didset)来遍历该列表,并在它们自己的后台线程中单独获取每个。每个单独的线程完成后,它会将其结果添加到 table 数组。您无法控制这些后台线程何时结束。
我相信 parse 有一个同步 get 方法。我不确定当前的语法。另一种选择是查看您是否可以 "include" 初始请求的图像文件字节,这将使整个调用成为单个后台调用。
另一种选择(可能是最好的选择)是使用另一条数据(字典等)来标记每个图像文件请求的位置。然后,当单个背景完成后,您就会知道该图像在最终数组中应该到达的位置。将下载的图像放在数组中您创建的字典告诉您的位置。
这应该可以解决您的异步问题。
我正在从我的 Parse 后端查询图像,并在 UITableView
中按顺序显示它们。尽管我一次一个地下载和显示它们,但它们在我的 table 视图中显示完全乱序。每张图片(专辑封面)对应一首歌曲,所以我得到的每首歌曲的专辑封面都不正确。有人会如此好心地指出为什么他们看起来不正常吗?
class ProfileCell: UITableViewCell {
@IBOutlet weak var historyAlbum: UIImageView!
}
class ProfileViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var historyAlbums = [PFFile]()
var albumCovers = [UIImage]()
// An observer that reloads the tableView
var imageSet:Bool = false {
didSet {
if imageSet {
// Reload tableView on main thread
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) { // 1
dispatch_async(dispatch_get_main_queue()) { // 2
self.tableView.reloadData() // 3
}
}
}
}
}
// An observer for when each image has been downloaded and appended to the albumCovers array. This then calls the imageSet observer to reload tableView.
var dataLoaded:Bool = false {
didSet {
if dataLoaded {
let albumArt = historyAlbums.last!
albumArt.getDataInBackgroundWithBlock({ (imageData, error) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data: imageData)
self.albumCovers.append(image!)
}
} else {
println(error)
}
self.imageSet = true
})
}
self.imageSet = false
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Queries Parse for each image
var query = PFQuery(className: "Songs")
query.whereKey("user", equalTo: PFUser.currentUser()!.email!)
query.orderByDescending("listenTime")
query.limit = 20
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
if let albumCover = object["albumCover"] as? PFFile {
// Appending each image to albumCover array to convert from PFFile to UIImage
self.historyAlbums.append(albumCover)
}
self.dataLoaded = true
}
}
} else {
println(error)
}
self.dataLoaded = false
})
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var profileCell = tableView.dequeueReusableCellWithIdentifier("ProfileCell", forIndexPath: indexPath) as! ProfileCell
profileCell.historyAlbum.image = albumCovers[indexPath.row]
return profileCell
}
}
}
你让它们乱序的原因是你正在为每个单独触发后台任务。
您可以在后台线程中一次性获得所有对象列表。那很好。然后,一旦你有了,你就调用一个方法(通过 didset)来遍历该列表,并在它们自己的后台线程中单独获取每个。每个单独的线程完成后,它会将其结果添加到 table 数组。您无法控制这些后台线程何时结束。
我相信 parse 有一个同步 get 方法。我不确定当前的语法。另一种选择是查看您是否可以 "include" 初始请求的图像文件字节,这将使整个调用成为单个后台调用。
另一种选择(可能是最好的选择)是使用另一条数据(字典等)来标记每个图像文件请求的位置。然后,当单个背景完成后,您就会知道该图像在最终数组中应该到达的位置。将下载的图像放在数组中您创建的字典告诉您的位置。
这应该可以解决您的异步问题。