NinjaDeveloper NinjaDeveloper - 7 months ago 23
Swift Question

calling alamofire asynchronous when I warp it service?

I have SingInService written in Swift to get user's login information i use alamofire to call HTTP post. I have problem after I ran the service and getting json user login info isn't passing to loginedUser in SingInService I tried dispatch_async(dispatch_get_main_queue()) but no use

var loginedUser = UserModel()

@IBAction func signedInAction(sender: AnyObject) {
let username:String = txtfUsername.text!
let password:String = txtfPassword.text!



let singInService = SingInService();
dispatch_async(dispatch_get_main_queue()) {
self.loginedUser = singInService.getUserCredential(username, password: password)
}
print(self.loginedUser._username);
txtfUsername.resignFirstResponder()
txtfPassword.resignFirstResponder()
}


class SingInService {

func getUserCredential(username:String,password:String)->UserModel
{
var authenticatedUser = UserModel()
let user = username
let password = password

let credential = NSURLCredential(user: user, password: password, persistence: .ForSession)

Alamofire.request(.GET, "https://httpbin.org/basic-auth/\(user)/\(password)")
.authenticate(usingCredential: credential)
.responseJSON { response in
switch response.result {
case .Success(let JSON):

let responseJson = JSON as! NSDictionary
let username:String = responseJson.objectForKey("user")! as! String
let authenticated:Bool = responseJson.objectForKey("authenticated")! as! Bool

authenticatedUser = UserModel(username: username,password:password,isAuthenticated: authenticated,isManager:false)

case .Failure(let error):
print(error)
}
}
return authenticatedUser;
}
}

Answer

Your sign in service needs to take a closure that executes when AlamoFire request completes. As you have it now, you immediately return authenticatedUser. You need to remember that if you create a service that that uses something that executes asynchronously to get results (like AlamoFire), then your service also will need to return those results asynchronously.

class SingInService {

    func getUserCredential(username: String, password: String, signInCallback: (userModel: UserModel) -> Void) {

       // call AlamoFire and in the Success case call the signInCallback
       // ...
       authenticatedUser = UserModel(username: username,password:password,isAuthenticated: authenticated,isManager:false)

       signInCallback(authenticatedUser)

    }
}

Notice that the service function does not return a value directly when you call it, instead you give it a closure that will be executed and provide the results once AlamoFire has retrieved the results.

You would use it like so:

singInService.getUserCredential(username, password: password) { (userModel: UserModel) in

    self.loginedUser = userModel
    print(self.loginedUser._username)
}

Once you have this working, to really make your service complete, you'll want to make sure your callback gets called no matter what happens, and carries along with not just the authenticated user, but also any possible error information.