我尝试使用其他解决方案没有运气。我需要将数据保存到UIImages数组中,因此在创建单元格时,它只需要从已制作的图像数组中分配图像即可。问题是它返回nil。另外,我需要确保图像井井有条。
/--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()
}
}
最佳答案
您实际上有一个相当复杂的问题。您有一个外部异步调用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()
函数。 (我忘了那一点。)