解析 getDataInBackgroundWithBlock 未按顺序获取

Parse getDataInBackgroundWithBlock not fetching in order

我正在从我的 Parse class 中获取一个字符串、NSDate 和一个 PFFile 来填充集合视图单元格

所有单元格都正确加载图像、日期和信息。信息和日期的排序正确(按日期升序)。但是当我构建一些图像时,有时会在不同的单元格中。我真的为此挠头。我猜这与我打电话的方式有关 mixPhoto.getDataInBackgroundWithBlock({

我确实尝试使用 dispatch_async(dispatch_get_main_queue())

仍然不走运...这是我的代码,有人有什么想法吗?

@IBOutlet weak var collectionView1: UICollectionView!


var mixPhotoArray : Array<UIImage> = []
var mixInfoArray: Array <String> = []
var mixDateArray: Array <NSDate> = []

override func viewDidLoad() {
    super.viewDidLoad()
    collectionView1.delegate = self;
    collectionView1.dataSource = self;

    self.queryParseMethod()
    self.getImageData()

    // Uncomment the following line to preserve selection between presentations
    // self.clearsSelectionOnViewWillAppear = false

    // Do any additional setup after loading the view.
}


func getImageData() {
    var query = PFQuery(className: "musicMixes")
    query.orderByAscending("date")
    query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
    for object in objects {


    let mixPhoto = object["mixPhoto"] as PFFile

        mixPhoto.getDataInBackgroundWithBlock({
            (imageData: NSData!, error: NSError!) -> Void in
            if (error == nil) {
                dispatch_async(dispatch_get_main_queue()) {
                    let image = UIImage(data:imageData)
                    //image object implementation
                    self.mixPhotoArray.append(image!)
                    println(self.mixPhotoArray[0])
                    self.collectionView1.reloadData()

                }
            }
            else {
                println("error!!")
            }

        })//getDataInBackgroundWithBlock - end

        }



    }//for - end

}

    func queryParseMethod() {

    var query = PFQuery(className: "musicMixes")
    query.orderByAscending("date")
    query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
        if error == nil {
            for object in objects {


    let mixPhoto = object["mixPhoto"] as PFFile




        let mixInfo = object["info"] as String
        let dateForText = object["date"] as NSDate


        //self.collectionView1.reloadData()

            self.mixDateArray.append(dateForText)
            self.mixInfoArray.append(mixInfo)
            self.collectionView1.reloadData()


                }//for - end
        }
        }
} // end of queryParseMethod


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()




        }



/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

// MARK: UICollectionViewDataSource

 func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
    //#warning Incomplete method implementation -- Return the number of sections
    return 1
}


 func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    //#warning Incomplete method implementation -- Return the number of items in the section
     println("I have \(mixPhotoArray.count) Images")
    return mixInfoArray.count


}

  //func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
  func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell:StreamCollectionViewCell = collectionView1.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as StreamCollectionViewCell

   cell.mixImage.image = mixPhotoArray[indexPath.item]
    cell.infoLabel.text = mixInfoArray[indexPath.item]

    // NSDate array into cell
    var dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
   cell.mixDateLabel.text = dateFormatter.stringFromDate(mixDateArray[indexPath.item])






     return cell
}

您将数据存储在 2 个数组中,mixPhotoArraymixInfoArray,但您不能保证它们的顺序相同。图像大小不同,因此它们将以不同的速度下载。你也不应该真的尝试一次下载超过 4 个,所以你当前的方案不是很好。

相反,您应该有一个字典数组或自定义数组 类,其中包含所有详细信息,并且在下载每张图像时会使用该图像进行更新。

显然这意味着您需要知道哪一个与您刚刚下载的图像相关联,因此您需要在块中捕获此字典/实例以便更新它。

您可以按原样在 2 个数组中执行此操作,只要您捕获图像所在位置的索引并将图像插入数组的正确位置即可。

正如 Wain 所说,我认为主要问题是由于您的图像以不同的速度下载,因此它们不一定按顺序附加到您的阵列中。不过,我不建议您使用字典,而是建议您在仍然使用数组的同时规避该问题:

// Declare your mixPhotoArray such that it can store optionals
var mixPhotoArray : Array<UIImage?> = []

func getImageData() {

    var query = PFQuery(className: "musicMixes")
    query.orderByAscending("date")
    query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
        // Initialize your array to contain all nil objects as
        // placeholders for your images
        self.mixPhotoArray = [UIImage?](count: objects.count, repeatedValue: nil)
        for i in 0...objects.count - 1 {

            let object: AnyObject = objects[i]
            let mixPhoto = object["mixPhoto"] as PFFile

            mixPhoto.getDataInBackgroundWithBlock({
                (imageData: NSData!, error: NSError!) -> Void in
                if (error == nil) {
                    dispatch_async(dispatch_get_main_queue()) {
                        let image = UIImage(data:imageData)
                        // Replace the image with its nil placeholder
                        // and do so using the loop's current index
                        self.mixPhotoArray[i] = image
                        println(self.mixPhotoArray[i])
                        self.collectionView1.reloadData()
                    }
                }
                else {
                    println("error!!")
                }

            })

        }

    }

}

然后在 collectionView:cellForItemAtIndexPath 内,您可以有条件地设置图像,使其仅在准备就绪后显示:

if mixPhotoArray[indexPath.item] != nil {
    cell.mixImage.image = mixPhotoArray[indexPath.item]
}