Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift Async completion to return an Array in custom class

I'm going to try to explain this as best as I can.

I am using Parse.com and returning data from a Parse database class. I want to put this parse.com call in its own function in a custom class. The problem I am having is the completion. Where does it go? I've tried many different versions of adding it to my function but it isn't working.

Here is the function that takes the class name, table name, and sort descriptor and returns an array:

func queryDataInBackgroundWithBlock(parseClass:String, parseObject:String, sortDescriptor:NSSortDescriptor) -> [Any]

When I add the completion to it I use (which may not be correct):

func queryDataInBackgroundWithBlock(parseClass:String, parseObject:String, sortDescriptor:NSSortDescriptor, completion: (result: Any)->Void)

Now inside the function I use the Parse.com code to go out and get the data

    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]!, error: NSError!) -> Void in
        if error == nil {

            // Do something with the found objects
            for object in objects {
                self.arrayOfObjects.append(object[parseObject]!)
            }

        } else {
            // Log details of the failure
            println("Error: \(error) \(error.userInfo!)")
        }

    }

My goal here is to send parameters to my class function, get the data from parse.com and then return the data as an Array AFTER the async call

I am trying to call it like this:

myClass.queryDataInBackgroundWithBlock("databaseName", parseObject: "columnName", sortDescriptor: orderBy){
    (result: Any) in
    println(result)
}

It's almost like it is a nested completion. How do I return the array after it is completed? Is it handed off to the function which then returns it, or does it need to return in the nested code, or what? It retrieves the data but the problem is the return AFTER completion.

UPDATE: As I stated in the comment below:

query.findObjectsInBackgroundWithBlock({
    (objects: [AnyObject]!, error: NSError!) -> Void in
    if error == nil {

        // Do something with the found objects
        for object in objects {
            self.arrayOfObjects.append(object[parseObject]!)
        }

    } else {
        // Log details of the failure
        println("Error: \(error) \(error.userInfo!)")
    }

}, completion: {
     //do something here
})

This is returning the error: "Extra argument completion in call" I'm not sure how to add the completion at the end of the block so I added () around the block and inserted the completion. This is obviously wrong but I'm not sure how to add the completion at the end of the block as matt has suggested

UPDATE 2:

    func queryDataInBackgroundWithBlock(parseClass:String, parseObject:String, sortDescriptor:NSSortDescriptor) -> [Any]{
        var query = PFQuery(className:parseClass)

        if sortDescriptor.key != "" {
            query.orderBySortDescriptor(sortDescriptor)
        }

        query.findObjectsInBackgroundWithBlock {
            (objects: [AnyObject]!, error: NSError!) -> Void in
            if error == nil {

                // Do something with the found objects
                for object in objects {
                    self.arrayOfObjects.append(object[parseObject]!!)
                }

            } else {
                // Log details of the failure
                println("Error: \(error) \(error.userInfo!)")
            }

        }

        return self.arrayOfObjects  //<-- needs to move to completion
    }
like image 897
AppDever Avatar asked Dec 16 '14 05:12

AppDever


1 Answers

Inside the function queryDataInBackgroundWithBlock you receive the completion block under the name completion. It takes one parameter. So the last thing you do, after you have the data, is call it, handing it the data:

completion(result:myData)

And since query.findObjectsInBackgroundWithBlock is itself async, you will need to make that call as the last thing inside the block of query.findObjectsInBackgroundWithBlock.

Like this:

func queryDataInBackgroundWithBlock(
    parseClass:String, parseObject:String, sortDescriptor:NSSortDescriptor, 
    completion: (result: Any)->Void) 
{
    var query = PFQuery(className:parseClass)

    if sortDescriptor.key != "" {
        query.orderBySortDescriptor(sortDescriptor)
    }

    query.findObjectsInBackgroundWithBlock {
        (objects: [AnyObject]!, error: NSError!) -> Void in
        if error == nil {

            // Do something with the found objects
            for object in objects {
                self.arrayOfObjects.append(object[parseObject]!!)
            }

        } else {
            // Log details of the failure
            println("Error: \(error) \(error.userInfo!)")
        }
        completion(result:self.arrayOfObjects)
    }

}
like image 116
matt Avatar answered Sep 19 '22 04:09

matt