Apple Dev Guild Week
By: Jeff Remer
Tags: Swift, iOS, Mobile

Apple Dev Guild Week

Swift Adoption

The team of developers that works on our iPhone and Apple Watch app spends the majority of its time working on feature development during the year. However, for a week in April the Apple Dev Guild had the opportunity to focus on platform health and the future of what writing iPhone and Watch apps looks like at Strava. Until this year writing iOS and WatchOS apps at Strava has meant writing entirely Objective-C. As a guild and as an organization we determined that it was important to begin our shift to Swift.

Why Swift? Why now?

Swift is a fast, safe, modern programming language. Swift was a fresh start for Apple. Unlike Objective-C, which comes with the baggage of being incrementally built on top of C, was designed from the ground up with features such as strict type safety and succinctness that help prevent programmer error, ease in maintenance, and let the programmer focus on logic and business rules.

Swift is the standard for writing iOS apps, partially because Apple declared it the official language, but also because it’s effective. Programmers are using it, it is the fastest growing programming language overall, and we’re at the stage where many iOS programmers have only ever written Swift. As a growing company we get candidates all the time that have only written Swift, which is perfectly fine with us since we tend to believe that being an effective iOS programmer is more about knowing the platform and having strong software engineering fundamentals. However, it was clear to us that in order to attract engineers we needed to evolve.

Strava’s iOS codebase is 7 years old and is almost entirely Objective-C. Swift has been around for years. Why hadn’t we really started adopting Swift until this year? At Strava we pride ourselves on adopting a healthy and reasonable mix of bleeding edge technologies and tried and true solutions. We actually did try out Swift in the early days, mostly experimentally, but every Swift release resulted in breaking API changes that just left a bad taste in our mouth. We witnessed several situations where other companies had to repeatedly rewrite their apps written in early versions of Swift and had a hard time coping with API changes across Xcode releases. As time went by and our codebase grew substantially we just simply didn’t risk making the switch, at least until the benefits started to clearly outweigh the disadvantages.

By the time Swift 4 was released it seemed like its maturity was commensurate with ours and we decided to dive fully in. As a guild we spent some time during the latter half of 2017 ensuring that we were all roughly on the same page as far as technical aptitude in Swift so that engineers could review each other’s code without getting completely lost. At the start of 2018 we decided that all new files should be written in Swift. We have a long way to go, but as of this writing our codebase is approximately 6% Swift and 94% Objective-C. That may not seem like much, but in a codebase of thousands of files and hundreds of thousands of lines of code going from zero Swift to just over 6% this year is a good start.

Building up our infrastructure

We started adopting Swift at the beginning of the year with enough in our toolbox to keep us working without slowing down product development, but we didn’t lay down a lot of ground rules. We trusted that the nature of Swift’s syntax and type safety would be enough to get us going and avoid the need to rely on manually checking a style guide in order to prevent us from shooting ourselves in the foot. We did integrate SwiftLint early on and have adjusted the set of rules we use over time to suit our needs. Developers report that they are pleased that an impartial robot tells them something is wrong with their code at compile-time, rather than getting nitpicked by their colleagues in pull requests.

Xcode 9.3 and Swift 4.1 Update

Guild week coincided nicely with the release of Xcode 9.3 and Swift 4.1. We spent some time ensuring that our existing Swift code was Swift 4.1 compatible and we updated our project settings to take advantage of the language update.

Swift dependency injection with Swinject

We’ve used Typhoon as our dependency injection framework on iOS for many years and it’s served us well. Although Typhoon supports Swift, we’ve viewed our Swift adoption as an opportunity to try out new things. During guild week we gave Swinject a try as a lightweight, pure Swift alternative to Typhoon.

BDD with Quick and Nimble

Behavior driven development offers an appealing refinement to TDD that can help organize thinking around testing the behavior of your application, especially when compared with traditional unit testing practices. BDD is used widely by the Web guild and we have used both Cedar and Kiwi in the past at Strava in Objective-C, but we kept returning to regular XCTestCases. BDD in Swift regains some of the elegance lost in BDD in Objective-C, so we decided to give it another shot by integrating Quick and Nimble. Quick is similar to RSpec in that it has helped us write more understandable and thorough tests.

Miscellany

By the time guild week had started in April we were already habitually writing Swift, so the entire focus that week wasn’t just on further Swift adoption. We had a growing laundry list of improvements we hoped to make across the app and across our development toolchain, so we set out to accomplish some of them while we could devote a relatively large chunk of time.

Some of these improvements included:

Migrating from HockeyApp to Crashlytics

Automating integration of internal Cocoapod updates

Updated our iPhone recording code to use the modernized Strava for Apple Watch recording code

Added flexibility to our internal URL routing mechanism

Looking forward

Strava’s second guild week is on the horizon and the Apple Dev Guild is taking some inspiration from the Android guild’s modularization efforts. We’re going to largely focus on modularizing our codebase further with the goals of establishing an architecture that is easier and less brittle to work with. We have some of this architecture in place already and it’s shown to help make working in a large code base feel small and manageable again. Aside from a qualitative improvement in coding confidence we want to establish empirically that these efforts are worth our time. We’ll begin tracking and analyzing build and test times. Alongside our Swift adoption our hope is that a more modular architecture leads to an more stable, more testable, and faster app.