• Backend API Documentation in Swift
  • The Nuggets translation Project
  • Translator: Nicolas Li
  • Proofread by: Siegen, DeadLion

I recently started working on a brand new project, and I’m trying out some new design patterns as I start working on Swift 3. One pattern I’m using is the request and response model. The “cool” name is a Struct in my documentation for this backend API. Let’s look at an example:

import Alamofire

protocol Request { var path : String { get }
    var method : Method { get }
    func parameters(a)- > [String : AnyObject]
}

struct AuthRequest : Request { let path = "auth" let method = Method.POST var password : String var password_verify : String var name : String var email : String func parameters() -> [String : AnyObject] { return ["password" : password, "password_verify" : password_verify, "name" : name, "email" : email] }
}Copy the code

We declare a Request protocol, and it pretty much lays out everything you need to know to make an API Request.

  • Need to add to base address (URL), which in this case isauth
  • HTTPMethods (GET.POST.PUT.DELETEEtc.)
  • The parameters required by the endpoint

You can extend the protocol for required information, such as a specific ContentType or other HTTP header. You can imagine adding some validation rules, completion handling, or anything related to this protocol network request.

All of this should look like a concise API document that provides some framework and type-safety validation for your network operations. You can turn these request constructs into your favorite web client. I have an example of Alamofire

class Client {
    var baseURL = "http://dev.whatever.com/"

    func execute(request : Request, completionHandler: (Response<AnyObject, NSError="">) -> Void){
        Alamofire.request(request.method, baseURL + request.path, parameters: request.parameters())
            .responseJSON { response in
                completionHandler(response)}}}Client(a).execute(request: AuthRequest(/*Insert parameters here*/), completionHandler: { response in})Copy the code

We pass the AuthRequest object to Alamofire, which needs a generic object to validate the Request protocol. It constructs and executes a network request using properties/methods specified in the protocol.

We have now defined the request structure and used it to simply access the server. We now need to deal with the response. Our AuthRequest returns a user JSON object that is not too large, and we need to serialize it into a Swift object.

struct UserResponse {
    var _id : String
    var first_name : String
    var last_name : String

    init(JSON: [String : AnyObject]) {
        _id = JSON["_id"] as! String
        first_name = JSON["first_name"] as! String
        last_name = JSON["last_name"] as! String}}/* Inside our completion handler */
var user = UserResponse(JSON: response.result.value as! [String : AnyObject])
Copy the code

This implementation is not too fancy, but it still records the properties of the response object. You can create a protocol that defines a JSON initializer, but using a simple structure is good enough for me so far.

Do you find any problems with this implementation? Is there any way I can use protocols/extensions more efficiently to compose my network request code? Please let me know! @iAmChrisTruman