Implement a Service-Oriented Architecture in Swift 5
Why using just MVC/MVVM/VIPER isn’t enough
Why is just using MVC, MVVM, MVP, or VIPER not enough? These architectural patterns handle only the higher level (UI) of your application. But very often, you also have to implement network managers, API clients, data sources, persistence containers, and so on. Service-oriented architecture makes your life easier by structuring the interaction between the high-level and lower-level implementations.
In this piece, I’ll show you how you can implement a service-oriented architecture (SOA). I did it by using a demo app I created for my VIPER piece and refactoring it according to SOA recommendations.
The source code of the project is available on GitHub.
The root of the project is divided into three folders:
Supporting Files. The
Resources folder contains
Assets.xcassets, and the
Supporting Files folder contains
As you can see, in
Classes, we have the following folders:
ApplicationLayerfolder contains the
PresentationLayerfolder has two VIPER modules:
Entities[aka models in MV(X)]
Servicesfolder has three services we use in our app:
QuoteService, which fetches quotes from the API;
KingfisherService, which obtains image data from an URL; and
ImageDataService, which generates an image from that data
CoreLayerfolder contains all the helper files we’ll need to work with services:
ApiUrls, request configurators, and network clients
Define a Service
First, we need to provide a base functionality of a service that’ll be subclassed by specific services in the future:
Each service must have a unique
serviceName and a
ServiceRegistryImplementation, we’ll register our services in
Having the base implementation done, now we’re ready to define specific services for our app.
This service is responsible for fetching quotes from the API.
Here’s how we define it:
QuoteService, we implement the actual networking:
This service is responsible for fetching image data from an URL.
It’s defined similarly to the
KingfisherService, we implement image data downloading:
ImageDataService provides a
UIImage when given
Yep, no surprises. We use a similar implementation:
The data-to-image conversion implemented in the extension:
To make services available to use in the app, we define a
ServiceRegistryImplementation inside the
Let’s take a look at how we’d use the
QuoteService to fetch a list of quotes to be displayed in the
If you’re not familiar with the VIPER architecture, simply know the
QuotesInteractor handles all business logic related to the quotes screen by passing the
QuoteService as a dependency and calling its
getQuotes method. You could call the same method inside a
UIViewController if you were following an MVC architecture or a
ViewModel in the case of MVVM.
Similarly, this is how we use the
KingfisherService to display a character’s image in the
The usage of the
ImageDataService is also pretty straightforward but with some of the nuances of VIPER:
In VIPER, the
Presenter is responsible for receiving the result of a business operation from the
Interactor, preparing it into a UI-displayable format, and forwarding it to the
ViewController — which implements the
If you’re curious about different architectural patterns, feel free to check out my other related pieces:
Reactive MVVM and the Coordinator Pattern Done Right
With Swift 5, RxSwift, and RxDataSources
How To Implement a VIPER Architecture in Your iOS App With Swift 5
With handy Xcode templates and a reference repo
Implement a Model-View-Presenter Architecture in Swift 5
Using the Realm database as a business logic layer
Thank you very much for reading!