Swift Alamofire SwiftyJSON Asynchronous/Synchronous Class Methods
Asked Answered
K

1

6

So I currently have the following:

class ViewController: UIViewController {

class Identity{
    let baseUrl = "superSecretURL"
    var _username: String = ""
    var _password: String = ""
    var _apiKey: String = ""

    init(){

    }

    init(username: String, apiKey: String){
        _username = username
        _apiKey = apiKey
    }

    init(username: String, password: String){
        _username = username
        _password = password
    }

    func loginPassword() -> String{
        var loginJSON = ["auth": ["passwordCredentials": ["username": _username, "password": _password]]];
        var returnJSON: String

        request(.POST, baseUrl, parameters: loginJSON, encoding: .JSON)
            .responseJSON { (request, response, data, error) in
                if let anError = error
                {
                    // got an error in getting the data, need to handle it
                    println("error calling POST on /posts")
                    println(error)
                }
                else if let data: AnyObject = data
                {
                    // handle the results as JSON, without a bunch of nested if loops
                    let post = JSON(data)
                    // to make sure it posted, print the results
                    println("JSON Returned")
                }
        }
    }
}

var i = Identity(username: "secretName", password: "complicatedPassword")

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    println("Before Call")



    println("After Call")

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


}

Basically I would like to be able to call the println("Before Call") then receive a response from the loginPassword() method and then println("After Call"). This is I believe synchronous but I can't figure out a way to get it to work and the whole threads thing has baffled my head.

I basically want to be able to say:

if i.loginPassword(){ // do some login stuff }else{ // do some error stuff }

Any help or pointers appreciated.

Kearse answered 12/5, 2015 at 17:45 Comment(0)
I
8

You need to set a callback function to be called whenever you want inside your loginPassword() function.

This could be a way of achieving it:

func loginPassword(callback: ((isOk: Bool)->Void)?) -> String{
 var loginJSON = ["auth": ["passwordCredentials": ["username": _username, "password": _password]]];
 var returnJSON: String

 request(.POST, baseUrl, parameters: loginJSON, encoding: .JSON)
   .responseJSON { (request, response, data, error) in
      if let anError = error{
       // got an error in getting the data, need to handle it
        println("error calling POST on /posts")
        println(error)

        callback?(isOk: false)
      }
      else if let data: AnyObject = data{
      // handle the results as JSON, without a bunch of nested if loops
        let post = JSON(data)
       // to make sure it posted, print the results
        println("JSON Returned")

        callback?(isOk: true)
      }
    }
}

and then...

override func viewDidLoad() {
    super.viewDidLoad()

    var identity = Identity(username: "John Apleseed", apiKey: "213123123")

    identity.loginPassword { (isOK) -> Void in
        if (isOK) {
            //do good stuff here
        }else{
           // do error handling here
        }

    }
}

UPDATE

Also, your calling function can look like this:

override func viewDidLoad() {
    super.viewDidLoad()

    var identity = Identity(username: "John Apleseed", apiKey: "213123123")
    identity.loginPassword(handlePasswordRequest)
}

and you can add as many callback handlers as you may need without messing around with a bunch of nested closures...

private func handlePasswordRequest(isOK: Bool){
    if (isOK) {
        //do good stuff here
    }else{
        // do error handling here
    }
}

UPDATE 2

If you are in need to call a callback deep into the hierarchy of calls, then you will need to pass the callback as a parameter of every previous closures.

UPDATE 3

I would give a try to RxAlamofire and all about RxSwift

Illene answered 12/5, 2015 at 18:30 Comment(3)
Brilliant thanks! Is there a way to chain this together using promises so it doesn't look quite as nasty with nesting? This could potentially get 4-5 levels deep during the other half of the application?Kearse
Do you know how the original answer looks in Swift 2? It worked for me in swift 1.2 but now the error parameter seems to be removed. Here is my question about thisDisprize
@HugoAlonso I would love to see RxAlamofire Nesting of Callback example. Could you provide a gist for this? Thanks!Extol

© 2022 - 2024 — McMap. All rights reserved.