As we’re preparing to launch a new iOS app template for news reading, we had to come up with a scalable architecture for a news reader iOS app. Since we want our fully-coded template to be generic enough, in order to accommodate as many use cases as possible, we had to design our Swift code accordingly. Since many iOS apps can be designed in a similar manner, we thought our findings might be useful to other iOS developers who are interested in using the appropriate design patterns in their implementation.
The architecture described below is not only built for the most common scenarios we already identified, but also for the unforeseeable additional features that might come up in the future. So we had to pay a lot of extra attention when designing our Swift classes and the way they interact. This series of blog posts describes how we ended up designing our code. This is meant to be a design tutorial for all the iOS developers who are working on similar apps.
Popular features of a News Reader iOS app
Before describing our architecture for the News Reader iOS template, we need to list the set of features that are usually supported by all the news reading apps. These are a good starting point for an iOS developer since the design patterns used initially rely on the minimum viable product of the app. The most popular features we identified on almost all the news reader apps can be summed up as following:
- Retrieving data (news, categories, authors, etc) from different RESTful APIs, over the network
- Displaying lists of news categories
- Displaying lists of articles (category screen, author screen, archive, etc)
- Showing a full news article (this is the News Details View)
- Allowing users to engage with the news (reads, likes, comments, replies, shares, etc)
In addition to the above core functionalities, a decent number of news reading apps also support features like:
- Login/Sign up (often social login with Facebook/Twitter)
- Push notifications (to push breaking news or recently posted articles, etc)
- Richer news formats (photos, videos, 360 videos, etc)
The iOS template we are building is meant to be used by a large variety of clients (bloggers, magazines, etc), so our architecture will accommodate all these visible features.
Technical features of a News Reader iOS app
In addition to the above core functionalities that are directly visible to the users, an awesome News Reader app has to be fast, performant (in terms of data usage, speed, etc) and great looking. Because apps are always evolving, adding new features to your code should be as easy as possible. That’s why architecture is very important.
In order to address the problems of performance and scalability, our app will encapsulate a set of technical features, as described below:
- Image Download optimizations
- Image caching – this enhances speed and reduces the mobile data usage
- Asynchronous image download and background image processing – this improves performance by moving the workload off the main thread
- Multiple API endpoints – An app can use more than one API for data retrieval, so we’ll provide a generic way of hitting the endpoints, by encapsulating the API components and by decoupling them from the networking component.
- Support for multiple server response formats. We’ll only describe how to add the following two formats (which are the most common), but we’ll design our iOS app so that we’ll easily inject any other future format.
- Testability – We should be able to write unit tests for all of our Swift classes with as little code as possible.
Design principles for structuring a News Reader iOS app
Given the features that will be supported by our News Reader iOS app, we’ll define in this section a set of design principles, that will serve as guidelines when deciding on our components. These can easily be extrapolated to all the iOS apps you’re building and we are using the News Reader app example only for demonstration purposes.
- Separation of Concerns – This is probably the best advice on software architecture that can be said in 3 words. This doesn’t apply only to iOS programming, but to all software systems in general. The main idea is that every component in your system has one and only one concern. It serves the other components, by exposing one specific task to them. We’ll go into more details around the separation of concerns, in the next blog post.
- Protocol-oriented Programming is powerful. So we’ll use it as often as we can. The major advantage of this paradigm is that our system components are more decoupled, and they interact with each other via protocols. The enemy of software scalability consists of classes that are strongly tight together. Protocols give us an elegant way of decoupling our classes.
- Use MVVM rather than MVC. Especially when you factor in the two guidelines from above. By using view models, to mediate the indirect data flow between views and models (through view controllers), we’re taking advantage of the protocol-oriented programming principles, to achieve separation of concerns.
- Avoid singletons – Testing singletons is painful so we want to avoid them as much as possible. They are usually a hack around a problem, and in most cases, there’s always a wiser design alternative.
- Dependency injection rocks. There’s no better way to make your Swift code more testable than to inject dependencies everywhere you can. Your unit tests will look very clean if you went down this path since you won’t need to use mocks anymore. Instead, you will be using real objects, and inject them into the constructors of the class you’re testing. Mocks are verbose, ugly, painful and prone to bugs, so let’s avoid them as much as possible.
In the next blog post, we’ll continue our tutorial by diving into more concrete details. We’ll show how we built a scalable News Reader iOS app, with all the aforementioned features, by conforming to the design principles we outlined in this article. More soon!