getdatainbackgroundwithblock返回零

时间:2016-03-03 00:54:31

标签: ios arrays swift parse-platform

我尝试过使用其他解决方案但没有运气。我需要将数据保存到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()
    }
}

1 个答案:

答案 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()函数。 (我忘了那一点。)