Full-stack Swift – Part 2

No Comments

In the first part of this blog post, we have successfully built a simple Vapor web server.
Now we are going to complement it with an iOS app.

The app will be written in Swift and it will be using Google’s Protocol Buffers (from now on protobuf) for communicating with the server over HTTP.

The app should be able to:

  • Display the existing books that are stored on the server
  • Add new books to the server

Building the UI of the app is outside the scope of this blog post, instead we will focus on the network layer and working with protobuf.


Create a new Xcode Single View Application project.
Name it BookshelfApp.
Add the previously generated Bookshelf.pb.swift into your project in order to be able to work with Book and Shelf objects.
In order to be able to use this class, we need to add Apple’s protobuf runtime library to the project.

We will use Carthage for dependency management. If you don’t already have it installed, install it using the official instructions.

Create a Cartfile that will be used by Carthage for fetching dependencies:

$ echo 'github "apple/swift-protobuf"' >> Cartfile

Fetch dependencies listed in your Cartfile into a Carthage/Checkouts folder, and build each one of them by running:

$ carthage update --platform iOS

In your application’s target “General” settings tab, in the “Linked Frameworks and Libraries” section, drag and drop SwiftProtobuf.framework from the Carthage/Build folder.

In your application’s target “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script in which you specify your shell (ex: bin/sh), add the following contents to the script area below the shell:

$ /usr/local/bin/carthage copy-frameworks

and add the path to the SwiftProtobuf.framework under “Input Files”:

Now we can use parse bytes into and from Book and Shelf objects.


Although many iOS Developers prefer using libraries such as AFNetworking (ObjC) / Alamofire (Swift) for creating their network layer, but in my opinion you should minimize the number of dependencies whenever you can.
In the case of iOS and networking, Apple has done a really god job with the URLSession class, and I will be using it for the core of the networking layer.

Create an empty Swift file called BackendRequest.
In this file we will define a protocol that every backend request will need to implement:

protocol BackendRequest {
    var endpoint: String { get }
    var method: BackendRequestMethod { get }
    var headers: [String: String]? { get }
    var data: Data? { get }
    func didSucceed(with data: Data)
    func didFail(with error: Error)
    func execute()

Each request to the backend needs to have:

  • An endpoint that it’s targeting
  • HTTP method
  • HTTP headers
  • HTTP body data
  • A way to handle data it got from the server
  • A way to handle an error
  • Method to enable executing it

As you can see we are missing the BackendRequestMethod type.
It will be an enum with a raw value of String, define it just above the protocol definition:

enum BackendRequestMethod: String {
    case get, post, put, delete

Also, let’s define some HTTP headers that we will use for our request just above the protocol definition:

struct BackendRequestHeader {
    static let contentTypeOctetStream = ["Content-Type": "application/octet-stream"]
    static let acceptOctetStream = ["Accept": "application/octet-stream"]

Add an extension with a default implementation of the execute method that will execute the request on the shared instance (singleton) of the BackendService (not implemented yet), below the protocol :

extension BackendRequest { 
    func execute() {
        BackendService.sharedInstance.execute(backendRequest: self)

Finally, define typealiases for default request completion handling above the protocol definition:

typealias SuccessHandler = (Void) -> Void
typealias FailureHandler = (Error) -> Void
Milan Stevanovic

Milan Stevanovic is working for codecentric Serbia as an IT Consultant and is mainly involved in iOS app consulting and development.

You can follow him on Twitter.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon


Your email address will not be published. Required fields are marked *