Networking 🌐

As described in Getting Started we use Alamofire. Therefore we explain everything using Alamofire as networking library. Of course other libraries can be used, too. Also URLSession which is built into Foundation.

Client Wrapper

We wrap all networking requests in Client.swift where we provide static functions which can be used everywhere in the app. The functions themselves provide a success and failure blocks that are called asynchronously. Based on the example of the bank search feature of the Yoli API we will explain the basics of Client step by step.

Static Interface

In Client we write down every request as a static function which can be accessed from everywhere in the App. The static function to search for banks in Client looks like this.

static func bankSearch(for searchQuery: String, limit: Int = 20, 
                       success: @escaping Success<BankSearchPage>, 
                       failure: @escaping Failure) -> DataRequest? {
  // Define custom variables needed for the request.
  let variables: GraphQLVariables = [
    "search": searchQuery,
    "limit": limit
  ]

  // Perform request using 'bankSearch' query and defined variables
  return request(script: .bankSearch, variables: variables, 
                 success: success, failure: failure)
}

This allows the app to search for banks (e.g. in a ViewController) using something like this below.

Client.bankSearch(for: searchTerm, success: { [weak self] page in
  // Store found banks and reload view
  self?.foundBanks = page.bankSearch
  self?.tableView?.reloadData()

}, failure: { error in
  // Error occurred, handle it.
  print("Handle error")

})

In the static function in Client we use the generic Success and non-generic Failure blocks. These are only typealiases described like this, where ClientError is an enumeration which conforms to Swift.Error.

typealias Success<T: Codable> = (T) -> Void
typealias Failure = (ClientError) -> Void

Model Mapping

You might have noticed BankSearchPage which we use in the generic Success block. Basically this struct describes the concrete data result the Yoli API responses for a bankSearch request.

The implementation of BankSearchPage together with Bank looks like this.

struct BankSearchPage: Codable {
  let bankSearch: [Bank]
}

struct Bank: Codable {
  let shortName: String
  let bankCode: String
  let bic: String?
  let city: String?
}

Yoli API Response

In Using GraphQL in iOS we have described how the Yoli API responses are wrapped using GraphQLPage. BankSearchPage will be used as the generic type of GraphQLPage in the bankSearch request which then can map the whole response which should look something like this below.

{
  "data": {
    "bankSearch": [
      {
        "shortName": "N26 Bank Berlin",
        "city": "Berlin"
      }
    ]
  }
}

Query

The used query on the other hand looks like this.

query bankSearch($search: String!, $limit: Int) {
  bankSearch(search: $search, limit: $limit) {
    shortName
    bankCode
    bic
    city
  }
}

What's Next?

In order not to get too detailed, we recommend checking the example project where you can e.g. see the implementation of the used request function in Client. The inline documentation should guide you through the code.

On the next page we explain how we handle the Yoli API authorization in iOS.