I have 4 functions containing Parse query.findObjectsInBackgroundWithBlock. These are being called to grab data and then populate the table view. Using dispatch groups.
Here is two examples of my parse querys
func getEventImages() {
print("getEventImages enter")
dispatch_group_enter(self.group)
let query = PFQuery(className: "events")
query.orderByAscending("eventDate")
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]!, error: NSError!) -> Void in
// Initialize your array to contain all nil objects as
// placeholders for your images
if error == nil {
self.eventMainImageArray = [UIImage?](count: objects.count, repeatedValue: nil)
for i in 0...objects.count - 1 {
let object: AnyObject = objects[i]
let mainImage = object["mainImage"] as! PFFile
//dispatch_group_enter(self.group)
mainImage.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
let mainImage = UIImage(data:imageData)
self.eventMainImageArray[i] = mainImage
print("getEventImages appended")
}
else {
print("error!!")
}
})
}
}
print("getEventImages leave")
dispatch_group_leave(self.group)
}
}
func getEventInfo() {
print("eventInfo enter")
dispatch_group_enter(group)
let query = PFQuery(className: "events")
query.orderByAscending("eventDate")
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]!,error: NSError!) -> Void in
self.eventNameArray = [String?](count: objects.count, repeatedValue: nil)
self.eventInfoArray = [String?](count: objects.count, repeatedValue: nil)
self.eventDateArray = [NSDate?](count: objects.count, repeatedValue: nil)
self.eventTicketsArray = [String?](count: objects.count, repeatedValue: nil)
if error == nil {
for i in 0...objects.count - 1 {
let object: AnyObject = objects[i]
let eventName = object["eventName"] as! String
let eventInfo = object["eventInfo"] as! String
let eventDate = object["eventDate"] as! NSDate
let eventTicket = object["Tickets"] as! String
self.eventNameArray[i] = eventName
self.eventInfoArray[i] = eventInfo
self.eventDateArray[i] = eventDate
self.eventTicketsArray[i] = eventTicket
print("event info appended")
}
}
print("event info leave")
dispatch_group_leave(self.group)
}
}
And my dispatch_group_nofity
dispatch_group_notify(group, dispatch_get_main_queue()) { () -> Void in
print("Finished reloadDataFromServer()")
self.tableView.reloadData()
self.refreshControl?.finishingLoading()
}
}
The problem is that its hit and miss if the data gets retrieved quick enough before dispatch_group_leave(self.group) is called leading to reloading the tableview data too soon. I need to get this so the dispatch_group_leave gets called when the appending is completed.
There is no need for two methods to retrieve the data, no need to unpack the data into multiple arrays and no need to use dispatch groups.
All you need is a simple method to retrieve your event data
var events:[PFObject]=[PFObject]()
func getEventInfo() {
let query = PFQuery(className: "events")
query.orderByAscending("eventDate")
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]!,error: NSError!) -> Void in
if error==nil {
self.events=objects as! [PFObject]
self.tableView.reloadData()
} else {
print("Something went wrong! - \(error)"
}
self.refreshControl?.finishingLoading()
}
}
Then, you haven't shown your cellForRowAtIndexPath
but you would have something like
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! MyTableViewCell
let event=self.events[indexPath.row]
cell.eventName.text=event["eventName"] as? String
cell.eventInfo.text=event["eventInfo"] as? String
if let mainImageFile=event["mainImage"] as? PFFile {
mainImageFile.getDataInBackgroundWithBlock({
(imageData: NSData!, error: NSError!) -> Void in
if (error == nil) {
let mainImage = UIImage(data:imageData)
cell.mainImage= mainImage
}
else {
print("error!!")
}
}
return cell;
}
You can use a PFImageView
or a framework like SDWebImage
to handle image caching and putting a placeholder image in place while the image is loaded.
If you want to update an event is as easy as
var event=self.events[someindex];
event["eventName"]=newValue
event.saveInBackground()