解析getDataInBackgroundWithBlock不按顺序获取 [英] Parse getDataInBackgroundWithBlock not fetching in order
问题描述
我正在从我的Parse类中获取一个字符串,NSDate和PFFile来填充集合视图单元格
I am fetching a string, NSDate and a PFFile from my Parse class to populate the collection view cells
所有单元格均正确加载了图像,日期和信息.信息和日期已正确排序(按升序排列).但是,时不时地,当我构建某些图像时,它们将位于不同的单元中.我真的为此抓挠了我的头.我想这与我如何调用mixPhoto.getDataInBackgroundWithBlock({
All the cells load with image, date, info correctly. The info and date are ordered correctly (by ascending date). But every now and then when I build some of the images will be in a different cell. Im really scratching my head with this. Im guessing it has something to do with how I'm calling mixPhoto.getDataInBackgroundWithBlock({
我确实尝试过使用dispatch_async(dispatch_get_main_queue())
I did try and use dispatch_async(dispatch_get_main_queue())
还是没有运气...这是我的代码,有人有任何想法吗?
Still no luck... Heres my code, anyone got any ideas?
@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
}
像Wain所说,
推荐答案
我相信主要的问题是,由于图像的下载速度不同,因此不一定按顺序将它们附加到数组中.我不建议您使用字典,而是建议您在仍然使用数组的情况下避免该问题:
Like Wain said, I believe the main issue is that since your images are downloading at different speeds, they're not necessarily being appended to your array in order. Instead of recommending that you use a dictionary though, here's what I would recommend to circumvent that problem while still using an array:
// 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
中,可以有条件地设置图像,使其仅在就绪后出现:
Then within collectionView:cellForItemAtIndexPath
, you can set the image conditionally so that it only appears once its ready:
if mixPhotoArray[indexPath.item] != nil {
cell.mixImage.image = mixPhotoArray[indexPath.item]
}
这篇关于解析getDataInBackgroundWithBlock不按顺序获取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!