Sharing Swift Code Between iOS and Server Applications

In this tutorial, you’ll learn how share code between iOS and server applications. By Christian Weinberger.

Leave a rating/review
Download materials
Save for later
Share
Update note: Christian Weinberger updated this tutorial for Vapor 4 and to account for the availability of SwiftPM on iOS. Tim Condon wrote the original.

Using Swift on the server allows you to use the same language you know and love from iOS development. In this tutorial, you’ll learn how to share code between iOS and server applications — the holy grail of full-stack development!

You’ll create a shared library using Swift Package Manager (SwiftPM). Then, you’ll import the library into your iOS and Server-Side Swift projects.

This tutorial uses Vapor for the Server-Side Swift app, but the same principles apply to any Swift-based framework. In this tutorial, you’ll learn how to:

  • Extract common models into a shared package.
  • Integrate the shared package into an iOS application.
  • Integrate the shared package into a Vapor application.
Note: This tutorial assumes you’ve installed Docker and have some basic experience with it. See Docker on macOS: Getting Started to learn more about Docker and how to install it. Additionally, you should have some experience using Vapor to build web apps. See Getting Started with Server-Side Swift with Vapor 4 if you’re new to Vapor.

Getting Started

Start by clicking the Download Materials button at the top or bottom of this tutorial.

The starter project contains two applications:

  • til-vapor-backend: The Vapor project for the API.
  • til-ios-app: The iOS app to consume the API.

The projects for this tutorial are based on the TIL app from the Server-Side Swift with Vapor book. You can create acronyms in the TIL app so you can remember their meaning. There are three relevant models in the project:

  • Acronym
  • User
  • Category

Why Share Code?

Sharing code between your client and server reduces duplication and means you only have to make changes in one place. For example, when you fix a bug in business logic or add a new property to a model, it’s fixed in both apps.

Sharing models is especially beneficial with Swift. If you use the same models on iOS and the server, you don’t need to worry about how the apps send the models in requests. You can send and receive them with JSON, Protobuf or even XML. As long as you use the same encoders and decoders on both ends, thanks to Codable, they’ll work.

Exploring the Vapor Project

Navigate to til-vapor-backend within starter package. Double-click Package.swift to open the Vapor app in Xcode.

While you wait for the SwiftPM to resolve dependencies, check out the existing project in Sources/App:

Exploring the Vapor project

Pay particular attention to:

  1. Controllers: This directory contains all API controllers to get or create acronyms, categories and users.
  2. Middlewares: This contains a custom middleware, TILErrorMiddleware, that encodes the custom TILError to a JSON response.
  3. Migrations: This has migrations for Acronym, Category and User as well as a migration to seed the database with initial data.
  4. Models: This contains various models used in the project. They’re grouped in subdirectories for API models, database entities and errors.
  5. Utilities: This has a convenience extension to Request that validates if a request has a specific parameter and throws a custom TILError otherwise. Endpoints.swift configures all endpoints used in the project, which you’ll learn more about later.
  6. configure.swift / routes.swift: configure.swift contains anything needed to run the project. For example, middleware and database configuration, as well as the registration of the migrations. routes.swift registers all controllers as RouteCollection.

Running the Vapor Project

Now that you’re a little more familiar with what the project contains, it’s time to dive in!

Spinning up the Database

Before you can run the Vapor project, you have to spin up a PostgreSQL database. This is already defined in the docker-compose file accompanying the Vapor project.

Go into Terminal and navigate to til-vapor-backend within the starter package. The root folder holds docker-compose, which contains a couple of images. For now, you only need the database (db) image.

In Terminal, run:

docker-compose up --build db

This builds db and spins up the PostgreSQL database with credentials that match those provided in .env:

Running docker-compose to spin up the database

Running the Migrations

First, run the migrations to create the database tables and populate your initial data. In Xcode, navigate to Product ▸ Schemes ▸ Edit Scheme in the menu bar. Select Run ▸ Arguments and add migrate -y in Arguments Passed On Launch.

Adding a launch argument to run migrations

This tells Vapor to run the migrations when you run the project. By passing the -y flag, you’re skipping interactive mode and auto-accept running the migrations.

Note: Before you can run the Vapor project, you have to configure the working directory. Otherwise, your back end won’t be able to locate the .env file. Do this by going to Product ▸ Schemes ▸ Edit Scheme in the menu bar, navigating to Run ▸ Options and checking Use custom working directory. Select the project folder here — for example, {path_to_your_projects}/til-vapor-backend.

Now, build and run the project to run the migrations. Switch to the console to see the output:

The result of the migrations

To run the actual project, head back to the Arguments Passed On Launch section and uncheck migrate -y.

Removing a launch argument to run migrations

Build and run. In the console, you’ll see that the server has started:

[ NOTICE ] Server starting on http://127.0.0.1:8080

Testing the API Using a REST Client

Now, switch to the REST client of your choice. This tutorial uses Paw, but alternatives such as Insomnia, Postman or even curl work fine as well.

Note: If you’re using Paw, there’s a project file in the root of the sample project that already contains all endpoints preconfigured for you: rw-code-sharing-ios-vapor.paw.

Call GET http://localhost:8080/api/users to verify that your project runs fine and the database contains the test data:

Testing your API with PAW REST Client

The server should respond with four users. Now, move on to the iOS app.

Exploring the iOS Project

Navigate to til-ios-app within the starter package and open the iOS project in Xcode by double-clicking TILiOS.xcodeproj.

Have a look at the project:

Exploring the iOS project

  1. Models: This directory contains all the API models: Acronym, Category and User.
  2. Main.storyboard: This contains the iOS app’s storyboard with all its screens.
  3. ViewControllers: All ViewControllers that are used to present or create new entries are in this directory.
  4. TILAPI.swift: This file contains the actual implementation of the HTTP communication with your Vapor app.