Written by Michał Apanowicz
Published January 18, 2024

The Fundamentals of iOS at News Destinations Engineering

 

We firmly believe that access to information is not just a privilege – it’s a fundamental human right. At Schibsted, we have a simple mission: to make independent journalism thrive with products people love. Recent events like the global pandemic, the Russian invasion of Ukraine, and the conflict in Palestine show how important parts of our daily lives as human news are. Let’s face it – news is literally at your fingertips in 2023, with news apps as an indispensable source of information.

Today, I’m excited to invite you behind the scenes of iOS development at News Destination Engineering. Join me on a journey where you’ll witness how we deliver high-quality apps in Scandinavia.

The Team

At the heart of every product lies the dedication of its creators. Our tight-knit team comprises 8 individuals, across 3 cities spanning 2 countries. Within this group, we boast 4 skilled iOS Software Engineers, a Tech Lead, a Product Manager, a Product/UX Designer, and an Engineering Manager. During the pandemic, we evolved into a distributed team that works remotely in most cases. Our recruitment process is no walk in the park; we seek not only excellent engineers but also individuals who align with the unique culture at Schibsted. Remarkably, like clockwork, every other week sees us launching 14 apps on the App Store built from one code base.

App Strategy 

In any industry, even the most exceptional individuals can fall short unless united by shared goals. To maintain a cohesive vision and emphasise our direction, we anchor ourselves in three foundational pillars of our strategy: 

  • Native Brilliance – always provides the experience that users expect from the native application. 
  • Premium Subscriber Experience – we recognise the investment of our paying customers, so we are committed to providing an experience that meets or even exceeds their expectations.
  • Scalable Solutions – whatever we do – it’s essential that we can scale for the benefit of all our brands.

Architecture for Scale

As previously mentioned, our team consistently delivers 14 apps to the AppStore every other week—an achievement made possible by strategic architectural decisions spanning six years.

Our approach is a relatively common architecture in iOS development. We use the MVVM + Coordinators pattern to present screens. But the most important part that allows us to apply scale is using protocol composition for dependency injection (DI, you can read more here). Over time, our DI solution has evolved to accommodate:

  • Thread Safety – ensuring the creation of dependencies is thread-safe, and we can utilise concurrency. 
  • Dynamic Dependencies – the ability to create/recreate dependencies as needed
  • Dependencies Composition – our goal is to balance between shared dependencies – such as loggers, web service, and authenticators – common across all apps and brand-specific dependencies tailored to support unique features for each brand.

I like to see our approach as a white-label solution that preserves the flexibility for distinctive brand features. Each new feature undergoes careful consideration of how it can be scaled seamlessly across other brands. 

From the project perspective, we have a mono repo with multiple modules (+75 targets in Xcode – considering apps, tvOS app, tests, widgets). Managing such complexity is only possible with a tool called Xcodegen, mainly because much structure can be abstracted and reused. 

Tech Stack 

Our project is written 95% in Swift. The other 5% are scripts written in different languages that help us with the build process and other valuable things. We prefer to stick to the vanilla solutions that iOS SDK provides. We saw too many past projects that relied on external frameworks and were left with substantial technological problems / issues (do you remember RestKit, ReactiveCocoa, AFNetworking).

Tools

  • Xcode, Git client of choice (command line, Sourcetree, Tower)
  • GitHub Enterprise – where we keep code, discuss Pull Requests, automate some issues
  • Xcodegen – we use it to reduce the number of merge conflicts in the project but, more importantly, to easily maintain our modules of the project  
  • Figma – as our tool to collaborate with designers
  • Swiftlint – as a linter with customised lint rules 
  • Travis – is our current build system, but we are in the process of switching to GitHub actions 
  • Proxyman – for debugging traffic 
  • Jira – our issue tracker 
  • Slack and Google Meet for communication 

Libraries

We try to keep our 3rd party dependencies to a minimum; however, let’s be reasonable. You should not reinvent the wheel. Here is a short list of great tools that you may find interesting: 

  • Swift Concurrency and Combine 
  • Yoga – we have our native rendering solution for cross-platform articles and collections that uses Yoga under the hood
  • Swift Snapshot Testing – helps us make sure we didn’t regress with some UI but also our analytics are up to date 
  • Moustache – help us with some template solutions 
  • AVKit – as we maintain our custom player

Development Process 

Please note that this is a technical article, so I won’t delve into the entire product process here.

We start development of the feature with a Feature Kick-Off meeting where, together with PM and designers, we break designs into issues in Jira and start a new Epic. While developers sometimes participate in earlier design stages, it’s not a strict requirement. 

 At our daily meetings, each issue undergoes triage and is slotted into the backlog (version is assigned or they land in the void of backlog unassigned)

Our workflow is managed through a Kanban board, categorised into version swimlanes, featuring key columns: 

  • Backlog – issues ready for development
  • In progress – issues currently being tackled by developers 
  • Blocked – issues on hold  – awaiting another issue’s resolution 
  • Verification – completed issues

Closed issues are disappearing from the board to minimise distractions. We embrace the freedom to choose them, avoiding strict prioritisation at the ticket level (Responding to change over following a plan). Instead, we aim to keep the most crucial issues atop each column. Occasionally, the problems we encounter need solutions that may not involve writing a line of code.

When a developer picks up an issue, work is done on a separate branch. Developers can pair up to program some issues together when they see the benefit of such an approach. We know that context switching is expensive, so we try to follow the priorities from the chart below:

A Pull Request (PR) is generated upon completion, triggering our build system to run tests and ensuring the new code adheres to our linter requirements. Every PR needs at least one reviewer to verify that the code is doing what is intended and that it’s written in a way that matches our code quality.

QA & Testing

We trust developers to uphold product quality. That’s why we don’t have QA engineers in our team. This is a setup tailored for us – it could not work in your field. However, to fulfil the QA job, our team is still spending a small portion of time on manual testing. 

Here’s our approach to maintaining app quality:

  • Unit Tests: Thoughtfully crafted for business logic, we avoid the blind pursuit of 100% code coverage. Our focus is on efficient regression spotting without compromising maintenance efficiency.
  • Snapshot Tests: Two-fold purpose—ensuring UI presentation of vital features and validating JSON files for analytic data.
  • Manual Testing of Pull Requests: Beyond happy paths, our manual testing probes for edge cases and potential regressions.
  • Bug Bash: An hour-long collective testing session for the Release Candidate version precedes each AppStore shipment.

Meetings and communication 

We are a distributed team, with most members working remotely. Good communication is an essential skill for everyone in the team. In such circumstances, we need to maximise meetings.

Release Train 

We ship the version every two weeks to the AppStore. Our train starts on Monday and finishes on the second Friday when we send apps for submission. 

Planning 

A weekly meeting where we organise our Kanban board, determining the achievable number of issues and fostering a shared understanding.

Daily 

The most important of our routine, facilitated by a rotating Daily Captain, covers issues, questions, follow-ups, and PR reviews. Our Daily is structured as  below:

  • Screening: triaging incoming issues and accepting only those that are clear and ready for development.
  • Verification: ensuring PR-reviewed issues are verified and tested.  If anyone thinks there is still something to verify, the issue will stay in this state until the next day.
  • In Progress: Addressing ongoing issues, allowing team members to share queries and schedule follow-ups, focusing on PR reviews. During this part of the daily, we also ensure every PR has a reviewer.
  • Product Board: As Daily is very technically focused, we make sure to include design and product aspects. This part of the Daily offers insight into upcoming developer tasks and supports the design process.

Backlog Grooming 

We try to keep our machete sharp and our backlog small. During backlog grooming, we go through our backlog, removing irrelevant or low-value issues.

Bug Bash 

This meeting aims to spot regressions in our app and test apps on multiple devices with different iOS versions. The first part of the meeting focuses on manual testing, and then we do a special screening of found issues. During this time, we decided if we could ship the version or if we found release blockers. If bugs are found, we split them across the team to fix them ASAP.

Retro 

As every agile team, we strive to learn from our mistakes and adjust our team to the current setup and needs. Usually, we use a lean coffee format and do this together on the Retrium platform.

iOS and Android Show and Tell 

Fostering a presentation culture, this meeting involves collaboration with our Android counterparts to share features, discuss challenges, and exchange experiences.

“Scheduled Fun“

An intentionally whimsically named meeting serving as a weekend opener and week summary, providing a platform for team bonding, games, and lighthearted presentations.

Ad-Hoc meetings

Of course, in addition to our set-in-stone meetings – we have some on-demand meetings. Only with part of the team.

Final note 

I would like to emphasise that these foundations were built through the collaborative efforts of many brilliant team members and my dear friends. I want to thank everyone involved: Andrii, Anton, Axel, Claus, Gabriel, Hanna, Joanna, Jonas, Maciej, Marcin, Mathieu, Mattias, Natalia, Niclas, Vova, Yuwen.

Written by Michał Apanowicz
Published January 18, 2024