简体   繁体   中英

More efficient way of retrieving objects from array of pointers in Parse, then updating uitableview in Swift

I have a Parse "Event" object already passed in to the viewController. No need to query for it.

This "Event" object contains an array of pointers to Parse "Comment" objects.

I am interested in two properties of the "Comment" objects. Both are strings called "commentAuthor" and "commentText".

I have a UITableView that has prototype cells, which needs to display the "commentAuthor" and "commentText" strings.

It is currently functioning, but I'm not satisfied with the way I'm doing it, which is this:

var commentsArrayOfPointers: [AnyObject]?
var commentsArrayOfObjects = [PFObject]()

func dealWithCommentPointers() {

    //get array of pointers from "Event" object
    commentsArrayOfPointers = theEvent!["commentsArray"] as? [AnyObject]

    commentsArrayOfObjects.removeAll()

    //loop through each pointer, and "Fetch" its associated "Comment" object,
    //then append that "Comment" object to my array of "Comment" objects
    for comment in commentsArrayOfPointers! {

        comment.fetchIfNeeded()

        commentsArrayOfObjects.append(comment as! PFObject)

    }

    //print(commentsArrayOfObjects)

    self.tableView.reloadData()

}

Then, I build my table cells like so, pulling the data out of my previously filled "commentsArrayOfObjects":

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("commentCell",
      forIndexPath: indexPath) as! commentCellClass

    cell.commentCellNameLabel.text = commentsArrayOfObjects[indexPath.row]["commentAuthor"] as! String
    cell.commentCellCommentLabel.text = commentsArrayOfObjects[indexPath.row]["commentText"] as! String

    return cell
}

It works, but I'm not thrilled about using the Parse command "fetchIfNeeded()" on each comment object, because it is a synchronous function, meaning it is causing my app to pause before showing the table. I would prefer to use an asynchronous function, which would allow the rest of the view controller to load, and then the comments would populate the table as they become available.

I tried doing a fetchInBackgroundIfNeeded() which is an asynchronous command, but of course it doesn't finish before the prototype cells are built, resulting in a crash (because the array it is looking for data is nil).

I also tried setting a PFQuery on the "Event" I need (event though I already have the event, no need to re-query for it) and adding an "includeKey" on the "commentsArray" property of the "Event" class. Then at the end of the Query, I did a self.tableView.reloadData() , but this didn't work either. There seems to be a larger problem here, as the query never even seems to execute, and the table reloads, even though I have commented out the code to do so. Here is that attempt (which I think is closer to the correct solution to my problem):

func dealWithCommentPointers() {

    print("inside the function")

    var query = PFQuery(className: "Event")
    let objectIdToLookup = self.theEvent?.objectId
    query.whereKey("objectId", equalTo: objectIdToLookup!)
    query.includeKey("commentsArray")

    query.findObjectsInBackgroundWithBlock { (results, error) -> Void in

        if error != nil {
            print("Error found")
            print(error)
        }


        else {

            let eventArray = results as! [PFObject]

            let theEventToDisplayCommentsFor = eventArray[0] //this should always be [0]

            print("yo dude")

            self.commentsArrayOfObjects = theEventToDisplayCommentsFor["commentArray"] as! [PFObject]

            print("hey here i am!")

            print(self.commentsArrayOfObjects.count)

            self.tableView.reloadData() //even tried commenting this out, it is still called?!

        }

    }

}

So, any ideas?

Why not include all of the Comment objects in the array beforehand? My guess would be that you have performed a query on the previous view controller and that is how you have the Event object to pass in. When you perform that query, use includeKey on the array so all of the Comment objects are returned with the query at the same time.

If that can't be done, I would recommend adding a couple function to your table view for asynchronously grabbing the data from Parse and then reloading the table. Here's an example for doing that which I've posted before . In that example there is a UISearchController but the ideas are the same.

You should really be using a relationship for the comments rather than an array, then you have a query that you can run asynchronously to get the comments. Also, you need to change your table view setup so it doesn't crash when you don't have any comments yet. You don't show why it crashes so I can't help with that, but you should really have an activity indicator while the query is in progress and then replace it with the real cells or a cell indicating there are no comments yet.

Technically using the asynchronous fetch should work just as well for small numbers of comments, but as you add more comments you're making more network requests and pretty quickly you'll flood the network and they'll all fail.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM