GCD Implementation not working with PARSE Query (Swift)

339 views Asked by At



I've looked all over Stack Overflow and other web resources on how to handle the async PARSE query and storing this data into an array. I then use this array to populate a table in another view controller. Code structure is as follows:

AppController.swift:

public var BuisnessNames = [NSString]()
[...]
public func updateFeedsMap(){

    var query : PFQuery = PFUser.query()!
    var objects : [AnyObject]?
    var counter = 0

    query.whereKey("isProprietor", equalTo: true)
    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]?, error: NSError?) -> Void in

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            if error == nil {
                // The find succeeded.
                println("Successfully retrieved \(objects!.count) scores.")
                // Do something with the found objects
                if let objects = objects as? [PFObject] {
                    for object in objects {
                        dispatch_sync(dispatch_get_main_queue()) {
                            self.BuisnessNames.append(object ["BusinessName"] as! NSString)
                        }
                    }
                }
            } else {
                // Log details of the failure
                println("Error: \(error!) \(error!.userInfo!)")
            }
        }
    }
}

RootVC.swift (inherits from AppController):

override func viewDidLoad() {
    if isUserLoggedIn() {
        dispatch_async(dispatch_get_main_queue()){
            self.updateFeedsMap()
        }
    }

RootVC segues to a third view controller in ViewDidAppear() which uses BuisnessNames array to populate a tableview. However, I am current not getting any data through to the table. I've spent many hours on this and I am out of ideas, please help! Thank you.

2

There are 2 answers

2
Leo On BEST ANSWER

You error is you request data in viewDidLoad,the process is async. It will return first.

Then you fire a segue in ViewDidAppear(),but at this time,you have not receive any data from the server.So,you tableview is always empty.

Solution:

Make a callback when data is received. Then do whatever you want with the data

A simple callBack demo

public func updateFeedsMap(completion:()->()){

    var query : PFQuery = PFUser.query()!
    var objects : [AnyObject]?
    var counter = 0

    query.whereKey("isProprietor", equalTo: true)
    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]?, error: NSError?) -> Void in

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            if error == nil {
                // The find succeeded.
                println("Successfully retrieved \(objects!.count) scores.")
                // Do something with the found objects
                if let objects = objects as? [PFObject] {
                    for object in objects {
                        dispatch_sync(dispatch_get_main_queue()) {
                            self.BuisnessNames.append(object ["BusinessName"] as! NSString)
                        }
                    }
                    //Here your data prase is done
                dispatch_async(dispatch_get_main_queue(), { () -> Void in
                    completion()
                })
                }
            } else {
                // Log details of the failure
                println("Error: \(error!) \(error!.userInfo!)")
            }
        }
    }
}

Then,your call the function like this

 self.updateFeedsMap { () -> () in
        //Here do something with data,reloadTableview or whatever you like
    }
4
danh On

There's no need for the GCD code you've added. The findObjectsInBackground does the GCD work for you, and invokes the completion block on the main, which is where you want it to be.

You can remove the dispatches (both in viewDidLoad and in the find completion block). Just fill your table's datasource array and tell the table to reloadData. Remember the following other table view gotchas, like forgetting to connect datasource and delegate, or forgetting to initialize the array before filling it.