WhiteFlowerFactory

A simple URLSession wrapper


License
MIT
Install
pod try WhiteFlowerFactory

Documentation

WhiteFlowerFactory is a simple URLSession wrapper with support for both concurrent and serial request queues.

Installation with Cocoapods

pod 'WhiteFlowerFactory'

Usage

Right now all callbacks are completed on the main queue, though this is subject to change in the near future.

Get requests

To make a simple GET request:

WhiteFlower.shared.get(urlString: "") { response in
    switch response.result {
    case .success(let data): // do something with data
    case .failure(let error): // do something with network error
    }
}

Serialize response using Codable

If you have a type and want to serialize the response using Codable:

WhiteFlower.shared.get(urlString: "") { response in
    switch response.serializeTo(type: MyClass.self) {
        case .success(let myClassInstance): // do something with myClassInstance
        case .failure(let error): // do something with network error  
    }
}

Test if OK

sometimes you just want to make sure an object was created, and expect a response with an empty body. For that, use isOK():

WhiteFlower.shared.post(urlString: "https://www.facebook.com/postSomething", params: ["key": "value"], headers: nil, completion: { (response) in
    switch response.isOk() {
    case .success: // success
    case .failure(let error)
    }
}

POST requests

A sample POST request:

WhiteFlower.shared.post(urlString: "urlHere", params: ["testParam" : "param1"], headers: [HTTPHeader(field: HTTPHeaderField.authentication.rawValue, value: "Bearer xxxx")]) { (response) in
        
}

Providers - Type safe routing

To provide type-safe routing with WhiteFlowerFactory, it is recommended that you create an enum that adopts to the Provider protocol. Ideally, you will have 1 enum conform to the Provider protocol for each baseURL endpoint your app has. For example, suppose your app needs to connect to the Stripe API and the Facebook API. You would create an enum that conforms to the Provider protocol, like so:

enum Facebook: Provider {
    case login
    case getFriends
    
    var path: String {
        switch self {
        case .login: return "\(baseURL)/login"
        case .getFriends: return "\(baseURL)/me/friends"
        }
    }

    var baseURL: String { return "https://facebook.com" }

    static var name: String { return String(describing: Facebook.self) // this returns "Facebook" }
}

Then, likewise for Stripe:

enum Stripe: Provider {
    case chargeCard
    
    var path: String {
        switch self {
        case .chargeCard: return "\(baseURL)/charge"         
        }
    }

    var baseURL: String { return "https://api.stripe.com" }

    static var name: String { return String(describing: Stripe.self)  }
}

Now, you can make use of type safe routing:

WhiteFlower.shared.post(endPoint: Stripe.chargeCard, params: ["":""], headers: []) { (response) in
        
}

Serial network operations

To make requests serially (one after another, waiting until the previous request is finshed before starting the next request), just create an array of WhiteFlowerRequest objects and create a WhiteFlowerSerialQueue:

  let requests = [WhiteFlowerRequest(method: .get, urlString: "https://facebook.com"), WhiteFlowerRequest(method: .get, urlString: "https://google.com"), WhiteFlowerRequest(method: .get, urlString: "https://reddit.com/r/iosprogramming")]
  
  let queue = WhiteFlowerSerialQueue(operationQueue: OperationQueue())
  
  queue.start(requests: requests, operationCompletion: { (response) in
      // this completion is called after every indiviudal request is finished
      // so in this examlple, it will be called 3 times
  }) { (allResponses) in
      // this is called at the very end and gives an array of APIResponse objects
  }

Concurrent network operations

To make multiple requests concurrently and then receive a callback only once all requests have completed, use the WhiteFlowerConcurrentQueue class:

let requests = [WhiteFlowerRequest(method: .get, urlString: "https://facebook.com"), WhiteFlowerRequest(method: .get, urlString: "https://google.com"), WhiteFlowerRequest(method: .get, urlString: "https://reddit.com/r/iosprogramming")]

let queue = WhiteFlowerConcurrentQueue(requests: [], queue: DispatchQueue.main)
queue.execute { responses in
    // `responses` is an array of APIResponse objects
}

The responses array will return the responses in the same order that they were originally executed. So for the example above, the response object for the https://facebook.com request would be first, google would be second, and reddit.com/r/iosprogramming would be last