I am using Alamofire to make REST calls to my server to get, add, update, and delete objects. What I'm wondering is, is it possible (and recommended) to wrap the Alamofire calls into my own custom objects (DTO), so that I can simply do things like user.delete(id) and user.add(newUser) instead of having Alamofire code all over my codebase? If so, how can I do it so I can return the success and failure handlers (the "promise" from the javascript world)? Something like this:
user.add(newUser)
.success(userObject){
}
.error(response){
}
Here is my current code:
//register a user
let parameters = [“username”: txtUsername.text! , "password": txtPassword.text!]
Alamofire.request(.POST, “http://myserver.com/users", parameters: parameters, encoding: .JSON)
.validate()
.responseObject { (response: Response<User, NSError>) in
if let user = response.result.value {
self.user = user
}
}
}
User.swift
final class User : ResponseObjectSerializable, ResponseCollectionSerializable {
var id: Int
var firstName: String?
var lastName: String?
var email: String?
var password: String?
init?(response: NSHTTPURLResponse, representation: AnyObject) {
id = representation.valueForKeyPath("id") as! Int
firstName = representation.valueForKeyPath("first_name") as? String
lastName = representation.valueForKeyPath("last_name") as? String
email = representation.valueForKeyPath("email") as? String
password = representation.valueForKeyPath("password") as? String
}
static func collection(response response: NSHTTPURLResponse, representation: AnyObject) -> [User] {
var users: [User] = []
if let representation = representation as? [[String: AnyObject]] {
for userRepresentation in representation {
if let user = User(response: response, representation: userRepresentation) {
users.append(user)
}
}
}
return users
}
//Can I wrap my alamofire calls in methods like this:
func getById(id: Int)
func getAll()
func add(user: User)
func update (user: User)
func delete(id: int)
}
i think a static func is what you want , i wrote a example for it :
final class User{
var valueHandle :((AnyObject) -> ())?
var errorHandle :((NSError)->())?
func success(value:(AnyObject) -> ())->Self{
//pass success handle
self.valueHandle = value
return self
}
func error(error:(NSError)->())->Self{
//pass error handle
self.errorHandle = error
return self
}
static func getById(id: Int)->User{
return userRequest(.GET, urlString: "https://httpbin.org/get", param: ["foo": "bar"])
}
static func userRequest(method:Alamofire.Method , urlString:String ,param:[String: AnyObject]?) -> User {
let user = User()
Alamofire.request(method, urlString, parameters:param)
.validate()
.responseJSON { response in
switch response.result {
case .Success(let value):
//invoke with your back userobj
user.valueHandle?(value)
print(value)
case .Failure(let error):
user.errorHandle?(error)
}
}
return user
}
}
then you can use like :
User.getById(1)
.success { (value) in
print("value = \(value)")
}
.error { (error) in
print("error = \(error)")
}
hope it be helpful :D
Related
I am making my first attempt at using Realm in Swift. I have my model setup and I successfully receive the response using Alamofire and I map it to the object. I am then attempting to store the data in realm. It creates the object, but the values are the default values and not what is received from the backend. What am I missing? Here's the model:
import Foundation
import ObjectMapper
import RealmSwift
#objcMembers class LoginResponseModel: Object, Mappable {
dynamic var status = ""
dynamic var id = UUID().uuidString
dynamic var userId = 0
dynamic var authToken = ""
required convenience init?(map: Map) {
self.init()
}
convenience init(status: String, userId: Int, authToken: String) {
self.init()
self.status = status
self.userId = userId
self.authToken = authToken
}
override static func primaryKey() -> String? {
return "id"
}
func mapping(map: Map) {
status <- map["status"]
userId <- map["user_id"]
authToken <- map["auth_token"]
}
}
Here is where I attempt to save it:
APIHelper.shared.login(username: username!, password: password!, success: { (result) in
if let login = result {
if (login.status != "failed") {
let userId = login.userId
let authToken = login.authToken
UserDefaults.standard.setValue(String(userId), forKey: "USERID")
UserDefaults.standard.setValue(authToken, forKey: "AUTHTOKEN")
UserDefaults.standard.synchronize()
vc.modalPresentationStyle = .fullScreen
do {
let realm = try! Realm()
try realm.write {
realm.add(login)
}
} catch(let error) {
print(error)
}
InstanceID.instanceID().instanceID { (result, error) in
if let error = error {
print(error)
} else if let result = result {
self.sendToken(userId: String(userId), authToken: authToken, fcmToken: result.token)
}
}
self.present(vc, animated: true, completion: nil)
}
}
Any ideas?
API call:
public func login(username: String, password: String, success: #escaping(_ response: LoginResponseModel?) -> Void, failure: #escaping(_ error: Error?) -> Void) {
let url = "\(baseUrl)appLogin"
AF.request(url, method: .post, parameters: ["emailOrPhone": username, "password": password]).responseString { response in
print(type(of: response).self)
switch response.result {
case .success(let json):
let resp = LoginResponseModel(JSONString: json)
success(resp)
case .failure(let error):
failure(error)
}
}
}
I get the object here:
let login = realm.objects(LoginResponseModel.self).first
Value of object:
status = ""
id = "1820A5D4-A714-4774-9707-4709ED39B570"
userId = 0
authToken = ""
I was just wondering what would be the best way to call the same Web Service from Different View Controllers(at different time). What architecture or design should I follow? I don't want to write the same code in each View Controller.
In case of using Alamofire library I can suggest to use
class NetworkManager {
static let shared = NetworkManager()
static let alamofireManager: SessionManager = {
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.timeoutIntervalForRequest = TimeInterval(_TIMEOUT)
sessionConfiguration.timeoutIntervalForResource = TimeInterval(_TIMEOUT)
return Alamofire.SessionManager(configuration: sessionConfiguration)
}()
func performRequest(url: String,
method: HTTPMethod = .get,
parameters: [String: Any] = [String: Any](),
encoding: ParameterEncoding = URLEncoding.default,
contentType: String? = nil,
headers: HTTPHeaders = [String: String](),
success: #escaping(Data, Int) -> (),
failure: #escaping(CustomError) -> ()) {
debugPrint("NetworkManager is calling endpoint: \(url)")
NetworkManager.alamofireManager.request(url, method: method, parameters: parameters, encoding: encoding, headers: headers).validate().response { response in
guard let status = response.response?.statusCode, let data = response.data else {
if let error = response.error {
debugPrint("Error when calling endpoint \(url)")
failure(.unknownError(message: error.localizedDescription))
}
return
}
debugPrint("HTTP Status received: \(status)")
success(data, status)
}
} else {
failure(.noNetworkConnection)
}
}
Please feel free to modify failure handler with your custom error or whatever you like.
Of course then you need to serialise the response.
Create a base class for Alamofire request like that:
import Alamofire
/// Struct for create AlamofireRequestModal
struct AlamofireRequestModal {
/// Struct constant for Alamofire.HTTPMethod
var method: Alamofire.HTTPMethod
/// Struct constant for path
var path: String
/// Struct constant for parameters
var parameters: [String: AnyObject]?
/// Struct constant for encoding:ParameterEncoding
var encoding: ParameterEncoding
/// Struct constant for headers
var headers: [String: String]?
///method to get init
init() {
method = .post
path = ""
parameters = nil
encoding = JSONEncoding() as ParameterEncoding
}
}
///BaseService to call the api's
class BaseService: NSObject {
/// network variable for Reachability
let network = Reachability.init(hostname: "https://www.google.com")
/**
This is method for call WebService into Alamofire
- parameter alamoReq: this is AlamofireRequestModal type request
- parameter success: success response
- parameter failure: failer object
*/
func callWebServiceAlamofire(_ alamoReq: AlamofireRequestModal, success:#escaping ((_ responseObject: AnyObject?) -> Void), failure:#escaping ((_ error: NSError?) -> Void)) {
guard (network?.isReachable)! else {
debugPrint("\n No Network Connection")
return
}
let request = Alamofire.request(alamoReq.path, method: alamoReq.method, parameters: alamoReq.parameters, encoding: alamoReq.encoding, headers: alamoReq.headers)
// Call response handler method of alamofire
request.validate(statusCode: 200..<600).responseJSON(completionHandler: { response in
let statusCode = response.response?.statusCode
if let allHeaderField = response.response {
allHeaderField.setHeaders()
}
switch response.result {
case .success(let data):
if statusCode == 200 {
success(data as AnyObject)
} else {
failure(NSError.init(domain: "www.wen.com", code: 101010, userInfo: ["message": "Something went wrong. Please trt again."]))
}
case .failure(let error):
failure(error as NSError?)
}
})
}
}
Then create a service class according to use, like here I am creating Profile service class for login and registration and profile type all api's are added in this class so you can create multiple serice class according to use:
import Alamofire
///Profile service to call the profile api's
class ProfileService: BaseService {
/**
This is request to BaseService to get Login
- parameter email: User email id
- parameter password: User password to login
- parameter success: success response
- parameter failure: failure response
*/
func doLogin(email: String, password: String, success: #escaping ((_ response: AnyObject?) -> Void), failure: #escaping ((_ error: NSError?) -> Void)) {
var request = AlamofireRequestModal()
request.path = "www.yourpath.com"
request.parameters = ["email": email as AnyObject,
"password": password as AnyObject
]
callWebServiceAlamofire(request, success: success, failure: failure)
}
}
Now, You can call this doLogin method of Profile service from anywhere like Or you can create more layer like Model class and call this service from model class or You can call directly like this:
ProfileService().doLogin(email: "Email", password: "Password", success: { (response) in
// Code here for handle success response
}) { (error) in
// Code here for handle error
}
I would write a network manager class, that takes the web service parameters if any as arguments.
Here is a crude example of the architecture
class YourNetworkManager {
public func callSpecificWebService(argument : Type?, [optional closure to handle results]) {
// Generate the actual URL to be called here. Usually by
// appending a suffix to some constant base url
// The web service call mechanism goes here.
// This could either use the NSURLSession API
// or some third party library such as Alamofire
// Process the generic response conditions from the web service
// here. Pass on the specific parts to the calling method.
}
}
As I mentioned, this is a crude example. The more modularised you can make things, the better it will be.
Never pass your Views and/or ViewControllers to you NetworkManager class.
Suppose you have a NetworkManager class like this.
open class NetworkHelper {
class var sharedManager: NetworkHelper {
struct Static{
static let instance: NetworkHelper = NetworkHelper()
}
return Static.instance
}
func request(_ method: HTTPMethod, _ URLString: String, parameters: [String : AnyObject]? = [:], headers: [String : String]? = [:], completion:#escaping (Any?) -> Void, failure: #escaping (Error?) -> Void) {
let URL = "BASE_PATH" + "URLString"
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
switch response.result {
case .success:
completion(response.result.value!)
case .failure(let error):
failure(error)
guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
return
}
}
}
}
}
Now create a BaseViewController which inherit from UIViewController and write your API call with necessary parameters.
For example in an API call you only need userID as param all else is static.
class BaseViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
func makeThisApiCallWithUserID(userId: Int) {
NetworkHelper.sharedManager.request(.get, "api/v1/yourApiAddress", parameters: ["userId":userId as AnyObject],headers: ["Authorization":"Bearer agshd81tebsf8724j"], completion: { (response) in
}) { (error) in
}
}
}
No you should inherit those ViewController in which you want the same API call and you do not want to write the code again.
class FirstChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 123)
}
}
class SecondChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 13)
}
}
class ThirdChildViewController: BaseViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.makeThisApiCallWithUserID(userId: 3)
}
}
See I haven't write API code in FirstChildViewController, SecondChildViewController, ThirdChildViewController but still they can make the same API call with different parameters.
Do you use Alamofire?, if yes then I have good method for it, written in NetworkHelper Class.
import Foundation
import Alamofire
open class NetworkHelper {
class var sharedManager: NetworkHelper {
struct Static{
static let instance: NetworkHelper = NetworkHelper()
}
return Static.instance
}
func request(_ method: HTTPMethod
, _ URLString: String
, parameters: [String : AnyObject]? = [:]
, headers: [String : String]? = [:]
, onView: UIView?, vc: UIViewController, completion:#escaping (Any?) -> Void
, failure: #escaping (Error?) -> Void) {
let URL = BASE_PATH + URLString
Alamofire.request(URL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
.responseJSON { response in
switch response.result {
case .success:
completion(response.result.value!)
case .failure(let error):
failure(error)
guard error.localizedDescription == JSON_COULDNOT_SERIALISED else {
return
}
}
}
}
}
I am new to Swift, and am not able to figure out how to deserialize a JSON array to an array of Swift objects. I'm able to deserialize a single JSON user to a Swift user object fine, but just not sure how to do it with a JSON array of users.
Here is my User.swift class:
class User {
var id: Int
var firstName: String?
var lastName: String?
var email: String
var password: String?
init (){
id = 0
email = ""
}
init(user: NSDictionary) {
id = (user["id"] as? Int)!
email = (user["email"] as? String)!
if let firstName = user["first_name"] {
self.firstName = firstName as? String
}
if let lastName = user["last_name"] {
self.lastName = lastName as? String
}
if let password = user["password"] {
self.password = password as? String
}
}
}
Here's the class where I'm trying to deserialize the JSON:
//single user works.
Alamofire.request(.GET, muURL/user)
.responseJSON { response in
if let user = response.result.value {
var swiftUser = User(user: user as! NSDictionary)
}
}
//array of users -- not sure how to do it. Do I need to loop?
Alamofire.request(.GET, muURL/users)
.responseJSON { response in
if let users = response.result.value {
var swiftUsers = //how to get [swiftUsers]?
}
}
The best approach is the use Generic Response Object Serialization provided by Alamofire here is an example :
1) Add the extension in your API Manager or on a separate file
public protocol ResponseObjectSerializable {
init?(response: NSHTTPURLResponse, representation: AnyObject)
}
extension Request {
public func responseObject<T: ResponseObjectSerializable>(completionHandler: Response<T, NSError> -> Void) -> Self {
let responseSerializer = ResponseSerializer<T, NSError> { request, response, data, error in
guard error == nil else { return .Failure(error!) }
let JSONResponseSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let result = JSONResponseSerializer.serializeResponse(request, response, data, error)
switch result {
case .Success(let value):
if let
response = response,
responseObject = T(response: response, representation: value)
{
return .Success(responseObject)
} else {
let failureReason = "JSON could not be serialized into response object: \(value)"
let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
return .Failure(error)
}
case .Failure(let error):
return .Failure(error)
}
}
return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
}
}
public protocol ResponseCollectionSerializable {
static func collection(response response: NSHTTPURLResponse, representation: AnyObject) -> [Self]
}
extension Alamofire.Request {
public func responseCollection<T: ResponseCollectionSerializable>(completionHandler: Response<[T], NSError> -> Void) -> Self {
let responseSerializer = ResponseSerializer<[T], NSError> { request, response, data, error in
guard error == nil else { return .Failure(error!) }
let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let result = JSONSerializer.serializeResponse(request, response, data, error)
switch result {
case .Success(let value):
if let response = response {
return .Success(T.collection(response: response, representation: value))
} else {
let failureReason = "Response collection could not be serialized due to nil response"
let error = Error.errorWithCode(.JSONSerializationFailed, failureReason: failureReason)
return .Failure(error)
}
case .Failure(let error):
return .Failure(error)
}
}
return response(responseSerializer: responseSerializer, completionHandler: completionHandler)
}
}
2) update your model object like this:
final class User: ResponseObjectSerializable, ResponseCollectionSerializable {
let username: String
let name: String
init?(response: NSHTTPURLResponse, representation: AnyObject) {
self.username = response.URL!.lastPathComponent!
self.name = representation.valueForKeyPath("name") as! String
}
static func collection(response response: NSHTTPURLResponse, representation: AnyObject) -> [User] {
var users: [User] = []
if let representation = representation as? [[String: AnyObject]] {
for userRepresentation in representation {
if let user = User(response: response, representation: userRepresentation) {
users.append(user)
}
}
}
return users
}
}
3) then you can use it like that :
Alamofire.request(.GET, "http://example.com/users")
.responseCollection { (response: Response<[User], NSError>) in
debugPrint(response)
}
Source: Generic Response Object Serialization
Useful Link: Alamofire JSON Serialization of Objects and Collections
Since you are using Alamofire to make your requests why don't you give a chance to Hearst-DD ObjectMapper it has an Alamofire extension AlamofireObjectMapper. I think it'll save you time!
I would loop through them then add each user to an array (preferably a property of the VC and not an instance variable) but here is an example.
Alamofire.request(.GET, "YourURL/users")
.responseJSON { response in
if let users = response.result.value {
for user in users {
var swiftUser = User(user: user as! NSDictionary)
//should ideally be a property of the VC
var userArray : [User]
userArray.append(swiftUser)
}
}
}
You could also try EVReflection https://github.com/evermeer/EVReflection
It's even more simple, i.e. to parse JSON (code snippet taken from EVReflection link):
let json:String = "{
\"id\": 24,
\"name\": \"Bob Jefferson\",
\"friends\": [{
\"id\": 29,
\"name\":
\"Jen Jackson\"}]}"
you can use this class:
class User: EVObject {
var id: Int = 0
var name: String = ""
var friends: [User]? = []
}
in this way:
let user = User(json: json)
I have a function that download data using Alamofire and then I would like to return that data. Now I know that Alamofire runs asynchronously and in order to to return data I should use completionHandler, however I don't get it how to use it. Since I am not the first with such problem, I found some solutions to similar problems, yet I am not sure to apply them to my case. Here is my code:
func downloadImageFromServer(imageUrl: String) -> (String, String) {
var myData1 = String()
var myData2 = String()
Alamofire.request(.GET, imageUrl)
.responseImage { response in
switch response.result {
case .Success:
if let newImage = response.result.value {
myData1 = //returned image name
myData2 = //edited image name
}
case .Failure:
//Do something
}
}
return (myData1, myData2)
}
Should I do something like this:
func downloadImageFromServer(imageUrl: String, completionHandler: (String?, String?) -> ()) {
var myData1 = String()
var myData2 = String()
Alamofire.request(.GET, imageUrl)
.responseImage { response in
switch response.result {
//if user does have a photo
case .Success:
myData1 = //Something
myData2 = //Something else
completionHandler(myData1 as? String, myData2 as? String)
case .Failure:
//Print error
}
}
}
Update
Yes, my question is very similar to that other question, however in my case, code has to return 2 values and that's where I find difficulties.
Here's my code for gettin values:
func getImages(orders: String, completionHandler: (String?, String?) -> ()) {
justDoIt(orders, completionHandler: completionHandler)
}
and then
getImages(imgURL) { responseObject, error in
print(responseObject)
return
}
And it works, however I am able to access only first value of the two, how to access both?
Your approach is correct. You could use another variable in your closure to see if the request was called properly (or another variable in function, e.g. errorHandler). Example of usage:
downloadImageFromServer(imgURL) { (data1, data2) in
print("Data1: \(data1). Data2: \(data2)")
}
Basic example of adding success/failure variable to your function:
func downloadImageFromServer(imageUrl: String, completionHandler: (Bool, String?, String?) -> ()) {
var myData1 = String()
var myData2 = String()
Alamofire.request(.GET, imageUrl)
.responseImage { response in
switch response.result {
//if user does have a photo
case .Success:
myData1 = //Something
myData2 = //Something else
completionHandler(true, myData1 as? String, myData2 as? String)
case .Failure:
completionHandler(false, nil, nil)
//Print error
}
}
}
Usage of the improved version of downloadImageFromServer():
downloadImageFromServer(imgURL) { (succes, data1, data2) in
if success {
print("Success. Data1: \(data1). Data2: \(data2)")
} else {
print("Error. Data1: \(data1). Data2: \(data2)")
}
}
I use Swift 2 and Xcode 7.1.
I have a function who connect my users, but it will connect at my database with HTTP. I use Alamofire for execute this request. I want to know, from a view controller if the user is connected.
I have my function connect in a class. And i test connection in a ViewController.
Like this :
class user {
// ...
func connectUser(username: String, password: String){
let urlHost = "http://localhost:8888/project350705/web/app_dev.php/API/connect/"
let parametersSymfonyG = [
username, password
]
let url = UrlConstruct(urlHost: urlHost).setSymfonyParam(parametersSymfonyG).getUrl()
//var userArray = [String:AnyObject]()
Alamofire.request(.GET, url)
.responseString { response in
if let JSON = response.result.value {
var result = self.convertStringToDictionary(JSON)!
if result["status"] as! String == "success"{
let userArray = result["user"] as! [String:AnyObject]
userConnect = self.saveUser(userArray)
} else{
print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
}
return ""
}
}
}
// ...
}
class MyViewController: UIViewController {
// ...
#IBAction func connect(sender: AnyObject?) {
// CONNECTION
User.connectUser(self.username.text!, password: self.password.text!)
// CHECK
if userConnect != nil {
print("connected")
}else{
print("NotConnected")
}
}
// ...
}
First solution : Return
To do so would require that my function returns a Boolean.
Only I can not use return.
Alamofire.request(.GET, url)
.responseString { response in
if let JSON = response.result.value {
var result = self.convertStringToDictionary(JSON)!
if result["status"] as! String == "success"{
let userArray = result["user"] as! [String:AnyObject]
userConnect = self.saveUser(userArray)
} else{
print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
}
return "" // Unexpected non-void return value in void function
}
}
Second solution :
I can also test if the user has been logged, but before testing, I must wait for the function have finished loading.
users.connectUser(self.username.text!, password: self.password.text!)
// after
if userConnect != nil {
print("connected")
}else{
print("NotConnected")
}
I would prefer return a boolean. It will facilitate the processing.
Do you have a solution ?
I would suggest employing a completion handler in your connectUser method:
func connectUser(username: String, password: String, completion: #escaping (Bool) -> Void) {
// build the URL
// now perform request
Alamofire.request(url)
.responseString { response in
if let json = response.result.value, let result = self.convertStringToDictionary(json) {
completion(result["status"] as? String == "success")
} else {
completion(false)
}
}
}
You can then call it using:
users.connectUser(username.text!, password: password.text!) { success in
if success {
print("successful")
} else {
print("not successful")
}
}
// But don't use `success` here yet, because the above runs asynchronously
BTW, if your server is really generating JSON, you might use responseJSON rather than responseString, further streamlining the code and eliminating the need for convertStringToDictionary:
func connectUser(username: String, password: String, completion: #escaping (Bool) -> Void) {
// build the URL
// now perform request
Alamofire.request(url)
.responseJSON { response in
if let dictionary = response.result.value as? [String: Any], let status = dictionary["status"] as? String {
completion(status == "success")
} else {
completion(false)
}
}
}
If you've written your own server code to authenticate the user, just make sure you set the right header (because responseJSON not only does the JSON parsing for you, but as part of its validation process, it makes sure that the header specifies JSON body; it's good practice to set the header, regardless). For example in PHP, before you echo the JSON, set the header like so:
header("Content-Type: application/json");
The completion handler of your Alamofire.request method is asynchronous and it doesn't have a return type specified in its signature. Thats why you see an error when you provide a return statement in your completion handler closure.
You will have to split your request and response processing to separate methods and call the response processing method instead of using return statement.
Alamofire.request(.GET, url).responseString { response in
if let JSON = response.result.value {
var result = self.convertStringToDictionary(JSON)!
if result["status"] as! String == "success"{
let userArray = result["user"] as! [String:AnyObject]
userConnect = self.saveUser(userArray)
processSuccessResponse() //Pass any parameter if needed
} else{
print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
processFailureResponse() //Pass any parameter if needed
}
}
}
func processSuccessResponse() {
//Process code for success
}
func processFailureResponse() {
//Process code for failure
}
My preferred way of doing this is to call a function in the completion handler. You can also set a boolean flag in order to check if the user is connected at any given time.
func connectUser(username: String, password: String, ref: MyClass) {
Alamofire.request(.GET, url)
.responseString { response in
var userIsConnected = false
if let JSON = response.result.value {
var result = self.convertStringToDictionary(JSON)!
if result["status"] as! String == "success"{
let userArray = result["user"] as! [String:AnyObject]
userConnect = self.saveUser(userArray)
userIsConnected = true
} else {
print("ERROR-CONNECTION :\n Status :\(result["status"]!)\n Code :\(result["code"]!)")
}
} else {
print("Response result nil")
}
ref.finishedConnecting(userIsConnected)
}
}
}
class MyClass {
var userIsConnected = false
func startConnecting() {
connectUser(username, password: password, ref: self)
}
func finishedConnecting(success: Bool) {
userIsConnected = success
... post-connection code here
}
}