我尝试过使用其他解决方案但没有运气。我需要将数据保存到UIImages数组中,因此当创建单元格时,它只需要从已经制作的图像数组中分配图像。问题是它返回零。此外,我需要确保图像有序。
/--UPDATING YOUR POSTS AFTER YOU POSTED--\\
func updatePosts(){
if Reachability.isConnectedToNetwork() {
self.images.removeAll(keepCapacity: true)
let query = PFQuery(className: "Shoes")
query.whereKey("createdBy", equalTo: PFUser.currentUser()!.username!)
query.orderByDescending("createdAt")
query.limit = 1000
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
print("Successfully retrieved \(objects!.count) scores.")
for object in objects! {
let imageFile = (object["imageFile"] as! PFFile)
imageFile.getDataInBackgroundWithBlock{
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
let image = UIImage(data: imageData!)
self.images.append(image!)
}
}
self.ids.append(object.objectId as String!)
}
dispatch_async(dispatch_get_main_queue(), {
self.collectionView.reloadData()
})
}
else {
print(error)
}
}
} else {
print("Internet connection not available")
// This is Depreciated!!
let alert = UIAlertView(title: "No Internet connection", message: "Please ensure you are connected to the Internet", delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
}
答案 0 :(得分:1)
你实际上有一个相当复杂的问题。你有一个外部异步调用query.findObjectsInBackgroundWithBlock
,它将一个对象数组传递给它的完成闭包,这很好。
在该闭包中,您运行一个循环,创建一大堆异步调用来加载图像。这些电话不会在不可预测的时间内完成。
通常我会说使用调度队列和调度组,所以你可以等到所有任务完成,但我假设你没有选择重写imageFile.getDataInBackgroundWithBlock()
函数。
我要做的是添加一个实例变量taskCount
,它跟踪要完成的任务的数量,在主线程上运行一个闭包,每次异步下载完成时递减taskCount
,并在完成所有任务后告诉表视图重新加载:
//Put this outside the function and inside the definition of your class so it's
//an instance variable
var taskCount: Int
然后将您的调用重写为query.findObjectsInBackgroundWithBlock
:
query.findObjectsInBackgroundWithBlock
{
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil
{
print("Successfully retrieved \(objects!.count) scores.")
//Remember how many getDataInBackgroundWithBlock calls have to run
//before we're done
taskCount = objects.count
//create an array of optionals and fill it with nils
var tempImageArray = [UIImage?](count: objects.count, repeatedValue: nil)
for (index, object) in objects!.enumerate()
{
let imageFile = (object["imageFile"] as! PFFile)
imageFile.getDataInBackgroundWithBlock
{
(imageData: NSData?, error: NSError?) -> Void in
if error == nil
{
let image = UIImage(data: imageData!)
tempImageArray[index = image;
//We're done with this one, so tell the main thread
//to decrement the taskCount
dispatch_async(dispatch_get_main_queue())
{
taskCount--
if taskCount == 0
{
self.images = tempImages.map({$0!})
self.collectionView.reloadData()
}
}
}
}
}
}
该代码同时运行对imageFile.getDataInBackgroundWithBlock
的所有调用,但调用主线程以减少每个完成闭包中的taskCount
。通过递减主线程上的taskCount
,您可以避免竞争条件,并且只有在下载了所有图像并且self.images
数组已完全填充后才会重新加载表视图。
那应该有用。 (我在SO文本编辑器中写了这个,所以它可能需要小的清理。大括号看起来不正确,但它应该给你这个想法。)
我更改了上面的代码以保留列表中结果对象的顺序,然后再次编辑它以修复for循环以使用enumerate()
函数。 (我忘了那一点。)