0

I asked in an earlier question How to use completion handlers correctly. The response was excellent, but i was wondering how i would perform a similar task if the function was void rather than returning a value. For example, say i want to run a Parse query, that gathers information and stores it in some local variables to populate a UITableView

func loadParseData () {
    commentsArray.removeAll(keepCapacity: false)
    let query = PFQuery(className: "Comments")
    query.whereKey("answerId", equalTo: answerId)
    var tempArray : [comment] = []
    query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
        if let objects = objects {
            for object in objects {
                let newComment = comment(comment: object["commentText"] as! String, username: object["Username"] as! String)
                tempArray.append(newComment)
            }
            self.commentsArray = tempArray
            self.tableView.reloadData()
        } 
    }
}

Then upon calling the cellForRowAtIndexPath, i need to populate the table data with information from the parse query. Because of this, the loadDataFromParse function must finish running before the cellForRowAtIndexPath tries to access the data. How would i set up a completion handler to ensure this happens?

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! commentCellTableViewCell

    cell.commentTextField.text = commentsArray[indexPath.row].comment
    cell.usernameTextField.text = commentsArray[indexPath.row].username
    return cell
}

EDIT: The above code works perfectly when i call the loadDataFromParse function in viewDidLoad. It is when i call it again when the user pulls to refresh the tableView that the error occurs. I have also edited the code to be my exact code, due to the fact that some comments were indicating it might be helpful

Community
  • 1
  • 1
rohaldb
  • 589
  • 7
  • 24
  • your `findObjectsInBackgroundWithBlock ` will always complete before your `reloadData ` isnt it? Only when u call `reloadData ` your tableview only call to `cellForRowAtIndexPath ` and that time its always sure your parse query is complete, cant understand what is your problem – Tj3n Feb 05 '16 at 09:46
  • When i run cellForRowAtIndexPath, it tries to access an index of the results array that doesnt exist yet. The results array length is 0 because the code hasnt finished running and the program crashes – rohaldb Feb 05 '16 at 09:52
  • Can you not put some logic in the cell class... That way, when the completion handler finishes, it can deal with the data there and then and leave the tableView class alone. – Byron Coetsee Feb 05 '16 at 09:58
  • That is a possibility, but the logic i was considering implementing was a completion handler of the function. Do you not think this is a good approach to my problem? – rohaldb Feb 05 '16 at 09:59
  • There is no problem of completion handler here, it is doing it work as it should and reloading the data after storing the object in result array. I think The SO is quite confused about what causing the crash/empty array, for that you have to follow basic debugging procedure. – Vizllx Feb 05 '16 at 10:12
  • I would suggest that you load your data into a temporary array and then assign that array to your `results` property right before you call `reloadData` – Paulw11 Feb 05 '16 at 10:13
  • Please see my edit regarding the refresh. @Paulw11 i do this, but the error still occurs when i pull to refresh – rohaldb Feb 05 '16 at 10:15
  • What do you return in `numberOfRowsInSection`? The array can have 0 rows as long as you return 0 from that method. Can you show the code you are running in your pull refresh handler? – Paulw11 Feb 05 '16 at 10:16
  • I do not return anything. I set the cell text to be the data i pull from the query. The first time numberOfRowsInSection is called it crashes as it tries to set the first cell text, however the array length is 0 – rohaldb Feb 05 '16 at 10:19
  • You have to implement `numberOfRowsInSection` and return something? Also, is that the entirety of your `cellForRowAtIndexPath`? You need to dequeue a cell – Paulw11 Feb 05 '16 at 10:20
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/102684/discussion-between-paulw11-and-rohaldb). – Paulw11 Feb 05 '16 at 10:30

0 Answers0