---
title: 'Introducing Swish 1.0: Protocol Based Networking for iOS'
teaser: 'Swish, a protocol based networking library, aims to make your iOS application''s
  network layer unobtrusive and easy to test.

  '
tags: ios,swish,argo,swift,news,open source
author: Sid Raval
published_on: 2016-06-02
---

[Swish](https://github.com/thoughtbot/Swish) 1.0, our Swift networking library,
is out! Swish came to life through working on many client projects and writing
more or less the same networking stack over and over. Our goals with Swish are:

- Be able to test our networking layer.
- Keep the networking layer self contained.
- By default, decode JSON into domain objects via
  [Argo](https://github.com/thoughtbot/Argo).
- If we want to do something different than decoding JSON, it should be as
  painless as possible.

And so Swish was born!

## Reasonable Default Behavior

Our 90% use case is that we get JSON from an endpoint, and we want to decode it
into a struct via Argo. Swish makes that easy. Let's say you have an endpoint,
`GET https://www.example.com/comments/1`, that returns the following JSON:

```json
{
  "id": 1,
  "commentText": "Pretty good. Pret-ty pre-ty pre-ty good.",
  "username": "LarryDavid"
}
```

We'll model this with the following struct, and implement Argo's `Decodable`
protocol to tell it how to deal with JSON:

```swift
import Argo
import Curry

struct Comment: Decodable {
  let id: Int
  let text: String
  let username: String

  static func decode(json: JSON) -> Decoded<Comment> {
    return curry(Comment.init)
      <^> j <| "id"
      <*> j <| "commentText"
      <*> j <| "username"
  }
}
```

(n.b. if you're not familiar with the `Curry` library, check [this blog post]
out)

[this blog post]: https://thoughtbot.com/blog/introduction-to-function-currying-in-swift

We can model the request by defining a struct that implements Swish's `Request`
protocol:

```swift
struct CommentRequest: Request {
  typealias ResponseObject = Comment
  let id: Int

  func build() -> NSURLRequest {
    let url = NSURL(string: "https://www.example.com/comments/\(id)")!
    return NSURLRequest(URL: url)
  }
}
```

We can then use Swish's default `APIClient` to make the request:

```swift
let request = CommentRequest(id: 1)

let dataTask = APIClient().performRequest(request) { (response: Result<Comment, SwishError>) in
  switch response {
    case let .Success(value):
      print("Here's the comment: \(value)")
    case let .Failure(error):
      print("Oh no, an error: \(error)")
  }
}
```

And that's it!

## Customize via Protocols

Swish's defaults make decoding via Argo seamless, but if you want to customize,
provide a different implementation for any of the following protocols:

- `RequestPerformer` allows you to define how the `NSURLRequest` should be
  carried out
- `Deserializer` allows you to process the `NSData` from the response however
  you wish
- `Parser` allows to you convert the result of your deserialization into a
  `Representation` (e.g. `JSON`, by default)
- `Client` allows you to define how the objects implementing the above protocols
  are linked together.

Checkout the [Swish repository](https://github.com/thoughtbot/Swish) for more!
