Way back in Bite #93 we talked about creating a "router" for Alamofire that would generate URL requests from enum cases.

In most apps we'll likely end up with some version of that code to help communicate with the API for that particular app. It'd be great if there was some sort of "standard" way to write this code each time.

Today we'll look at a library called Moya that aims to provide this. Let's dive in. 🏊

Moya is a network abstraction layer that encapsulates calling Alamofire functions. It helps us avoid creating messy custom network abstractions in every project.

To use Moya in an app, we'll need an enum with a case representing each API endpoint we want to hit:

enum FirstOrder { case AllTroops; case Troop(String) }

Then we'll extend it to conform to Moya's TargetType protocol:

extension FirstOrder: TargetType {
  var baseURL: NSURL {
    return NSURL(string: "https://api.firstorder.galaxy.far.away")!
  }

  var path: String {
    switch self {
    case .AllTroops: return "/troops"
    case .Troop(let id): return "/troops/\(id)"
    }
  }

  var method: Moya.Method { return .GET }

  var parameters: [String: AnyObject]? {
    switch self {
    case .AllTroops: return ["sort": "recent"]
    default: return nil
    }
  }

  var sampleData: NSData {
    switch self {
    case .AllTroops:
      return "[{\"id\": \"FN-2187\"}]".dataUsingEncoding(NSUTF8StringEncoding)!
    case .Troop(let id):
      return "{\"id\": \"\(id)\"}".dataUsingEncoding(NSUTF8StringEncoding)!
    }
  }
}

Finally, we'll create a new Moya provider using our enum and make it available globally:

let FirstOrderAPI = MoyaProvider<FirstOrder>()

Now we can make requests like this:

FirstOrderAPI.request(.Troop("FN-2187")) { result in
  switch result {
  case .Success(let response):
    do {
      let json = try response.mapJSON()
      // TODO: Parse JSON
    } catch(let error) { handleError(error) }
  case .Failure(let error): handleError(error)
  }
}

This is just a taste, Moya has a ton to offer including some fantastic enforcement of good testing practices.

In conforming to the TargetType protocol, we're actually required to provde sampleData. We can also customize things further by providing an endpointClosure when creating our provider.

More info about Moya can be found at git.io/moya