Ramsy de Vos
Ramsy de Vos

Reputation: 1072

SWIFT: Passing variable from closure to function

I'm trying to create a function which returns an NSDictionary, which on its turn needs to be returned from a closure.

I'm relatively new to Swift and I'm having problems figuring this one out. Any help would be greatly appreciated.

// Takes a String, needs to return a NSDictionary

func login(action: String) -> NSDictionary 
{
    let command = NSURL(string: "\(connectionType)://\(url)/includes/api.php?username=\(username)&password=\(password)&accesskey=\(apiKey)&action=\(action)&responsetype=json")
    print(command!)

    let session = NSURLSession.sharedSession()

    // Get error here when changing Void > NSDictionary
    let task = session.dataTaskWithURL(command!) {
        (data, response, error) -> Void in 

        if error != nil {

            print(error!.localizedDescription)

        } else {

            do {
                let result = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as! NSDictionary

                print(result) // Need this returned

            } catch {
                // handle error
                print(error)
            }
        }
    }

    task.resume()

    return result As! NSDictionary // returns empty, because of -> Void??

}

Upvotes: 1

Views: 748

Answers (2)

NRitH
NRitH

Reputation: 13903

In your declaration of the closure's type

let task = session.dataTaskWithURL(command!) {
    (data, response, error) -> Void in
    /* closure body */
}

change the Void to JSONObject. But that's not all! You're trying to return something from a login function that makes an asynchronous call, and that's impossible. Instead, your login function itself needs to take a closure, and that closure will be where you do something with the result NSDictionary. So change your declaration of login to

func login(action: String, completionHandler: (NSDictionary) -> ())

and implement the completionHandler accordingly.

Upvotes: 2

Fonix
Fonix

Reputation: 11597

The problem is dataTaskWithURL is an asynchronous function, therefore it hasnt got around to executing the block yet before it returns the function.

what you need to do is either setup a function that can be called on self that will let self know when the block has executed and can pass you the result, or setup a protocol with a delegate that you can call to notify of the result

also, the -> Void inside the block is the return type of the block, you shouldnt really be returning anything inside that block anyway because nothing will actually happen with it since the parent function doesnt expect anything to be returned, hence why its Void

Upvotes: 2

Related Questions