Author Topic: Swift and Alamofire  (Read 7394 times)

cartic

  • Newbie
  • *
  • Posts: 2
    • View Profile
Swift and Alamofire
« on: June 16, 2015, 11:31:58 PM »
Kevin, I thoroughly enjoyed your "Learn to code in Swift" book and I am so glad I discovered your content. In this book you mentioned use of "Closure" to process asynchronous web requests in later part of the series. Does that mean it if covered in one of your other books or is it something you are planning on releasing in another book in the future?

Do you have any pointers on using the Generic Response Object Serialization of Alamofire and what exactly the code below means in your usual elegant and simple way?

Generic Response Object Serialization

Generics can be used to provide automatic, type-safe response object serialization.

Code: [Select]
@objc public protocol ResponseObjectSerializable {
    init?(response: NSHTTPURLResponse, representation: AnyObject)
}

extension Alamofire.Request {
    public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
        let serializer: Serializer = { (request, response, data) in
            let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
            let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
            if response != nil && JSON != nil {
                return (T(response: response!, representation: JSON!), nil)
            } else {
                return (nil, serializationError)
            }
        }

        return response(serializer: serializer, completionHandler: { (request, response, object, error) in
            completionHandler(request, response, object as? T, error)
        })
    }
}

final class User: ResponseObjectSerializable {
    let username: String
    let name: String

    required init?(response: NSHTTPURLResponse, representation: AnyObject) {
        self.username = response.URL!.lastPathComponent
        self.name = representation.valueForKeyPath("name") as String
    }
}

Alamofire.request(.GET, "http://example.com/users/mattt")
         .responseObject { (_, _, user: User?, _) in
             println(user)
         }

kjmcneish

  • Administrator
  • *****
  • Posts: 719
    • View Profile
Re: Swift and Alamofire
« Reply #1 on: June 17, 2015, 11:07:51 AM »
Glad you enjoyed the book! I've talked about asynchronous web requests in my iPhone Life magazine blog series, and it will eventually find its way into a book! http://www.iphonelife.com/blog/31369/unleash-your-inner-app-developer-part-37-amazon-web-services-your-ios-apps

Here's an explanation of the code you posted.

1. This is a protocol declaration named ResponseObjectSerializable. As shown in their sample code, you need to adopt this protocol on any object you want to serialize using Alamofire. It contains a single initializer method that accepts two parameters: response of type NSHTTPURLResponse and representation of type AnyObject.

Code: [Select]
@objc public protocol ResponseObjectSerializable {
    init?(response: NSHTTPURLResponse, representation: AnyObject)
}

2. In their example listed at the bottom of the code you posted, the User class adopts the ResponseObjectSerializable protocol and implements the required initializer. This code is grabbing values from the response and representation objects and storing them in the username and name constants.

Code: [Select]
final class User: ResponseObjectSerializable {
    let username: String
    let name: String

    required init?(response: NSHTTPURLResponse, representation: AnyObject) {
        self.username = response.URL!.lastPathComponent
        self.name = representation.valueForKeyPath("name") as String
    }
}

3. This code is showing you Alamofire's extension to the Request class. The extension contains a single responseObject:completionHandler method. The <T: ResponseObjectSerializable> declaration specifies a generic placeholder named T that adopts the ResponseObjectSerializable protocol. Whenever you see the T placeholder in this method, you can mentally replace it with ResponseObjectSerializable. So, for example, the completionHandler argument becomes: completionHandler: (NSURLRequest, NSHTTPURLResponse?, ResponseObjectSerializable?, NSError?). Ultimately, they're providing the source code so you can see what's happening inside this method.

Code: [Select]
extension Alamofire.Request {
    public func responseObject<T: ResponseObjectSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, T?, NSError?) -> Void) -> Self {
        let serializer: Serializer = { (request, response, data) in
            let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
            let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
            if response != nil && JSON != nil {
                return (T(response: response!, representation: JSON!), nil)
            } else {
                return (nil, serializationError)
            }
        }

        return response(serializer: serializer, completionHandler: { (request, response, object, error) in
            completionHandler(request, response, object as? T, error)
        })
    }
}

4. Now they're showing you how to use the responseObject method in your own code. As you can see, they are passing the User object as the generic parameter, which works because the User class adopts the ResponseObjectSerializable protocol.

Code: [Select]
Alamofire.request(.GET, "http://example.com/users/mattt")
         .responseObject { (_, _, user: User?, _) in
             println(user)
         }

Hope that helps!
Kevin

cartic

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Swift and Alamofire
« Reply #2 on: June 17, 2015, 04:57:16 PM »
Kevin,

Thank you so much for your time on this. The level of details in your response makes it extremely easy to understand what's going on. Earlier I got it working by just mucking around with the code until it worked now I know exactly know what's going on. This makes a world of difference. Again, thank you so much!!

- Karthik.

kjmcneish

  • Administrator
  • *****
  • Posts: 719
    • View Profile
Re: Swift and Alamofire
« Reply #3 on: June 18, 2015, 03:10:03 PM »
Glad to help!

Kevin