Search code examples
iosswiftswift2alamofire

Wrapping Alamofire calls into custom objects in Swift?


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) 

    }

Solution

  • 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