user3483697
user3483697

Reputation: 123

How to reload a tableview only once at the end of a parse query?

Essentially, I have built a tableviewcontroller with a PFQuery to load information for each individual cell and store it in a array. There are two calls to parse, one to store usernames into an array, and another one to check if the current user is "following" them.

var query = PFUser.query()

query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]!, error: NSError!) -> Void in
        self.users.removeAll(keepCapacity: true)   // users is an array declared globally

        for object in objects {
                var user:PFUser = object as PFUser
                var isFollowing:Bool
                if user.username != PFUser.currentUser().username {
                        self.users.append(user.username)
                        isFollowing = false
                        var query = PFQuery(className:"followers")
                        query.whereKey("follower", equalTo:PFUser.currentUser().username)
                        query.whereKey("following", equalTo:user.username)
                        query.findObjectsInBackgroundWithBlock {
                                (objects: [AnyObject]!, error: NSError!) -> Void in
                                if error == nil {
                                        for object in objects {
                                                isFollowing = true
                                        }

                                        self.following.append(isFollowing)
                                        self.tableView.reloadData()

                                } else {
                                        // Log details of the failure
                                        println(error)
                                }
                        }

                }
        }
}

If I call reloadData() at another place, the table will not display correctly. This makes my table loading inefficient..since the table reloads with every check for the "isfollowing" variable. How would I make it reload only once? After all the "isfollowing" variable have been appended? Can you please outline the solution step by step so I can get a general sense of direction and what to learn.

EDIT2:

In the code above I query to check which users the currentUser is following. If they are following them, I append "true" to the array "following". The code below is what I'm doing to checkmark the tableviewcells to show that they are following other users. With my original code, all the cells become checkmarked after scrolling up and down a couple of times, why?

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell

    if following.count > indexPath.row {

        if following[indexPath.row] == true {

            cell.accessoryType = UITableViewCellAccessoryType.Checkmark

        }

    }

    cell.textLabel.text = users[indexPath.row]

    return cell

}

EDIT: Wrong code posted originally.

Upvotes: 0

Views: 992

Answers (1)

linimin
linimin

Reputation: 6377

Use findObjects to call synchronously and put it in our own queue may helps.

// queue is declared as an instance property
let queue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL)

var query = PFUser.query()

dispatch_async(queue) {
    dispatch_async(dispatch_get_main_queue()) {
        self.users.removeAll(keepCapacity: true)   // users is an array declared globally
    }

    for user in query.findObjects() as [PFUser] {
        var isFollowing = false

        if user.username != PFUser.currentUser().username {
            dispatch_async(dispatch_get_main_queue()) {
                self.users.append(user.username)
            }

            var query = PFQuery(className:"followers")

            query.whereKey("follower", equalTo:PFUser.currentUser().username)
            query.whereKey("following", equalTo:user.username)

            // call findObjects synchronously
            if let objects = query.findObjects() {
                if !objects.isEmpty {
                    isFollowing = true
                }

                dispatch_async(dispatch_get_main_queue()) {
                    self.following.append(isFollowing)
                }
            }
        }
    }

    // notify table view to reload
    dispatch_async(dispatch_get_main_queue()) {
        self.tableView.reloadData()
    }
}

You can create a UITableViewCell subclass and override its prepareForReuse to reset accessoryType.

class MyTableView: UITableViewCell {
    override func prepareForReuse() {
        accessoryType = .None
    }
}

In your code, you didn't handle the case for following[indexPath.row] != true. If you don't want to subclass UITableViewCell, you can also reset the checkmark there.

Upvotes: 2

Related Questions