Codementor Events

Yummypets iOS App Stack

Published Oct 30, 2017Last updated Apr 27, 2018


Image courtesy of unsplash

This year is coming to an end and we’d like to share our iOS stack for the Yummypets App. Let’s do it!

Code

97% of the App is written fully in Swift. For a total of 46k lines of code.

MVC

The whole app is following the good’ol MVC Pattern. When controllers get too big, we refactor them into smaller controllers.

Core

All of our Models logic and Networking code is encapsulated in a Core.framework. This forces us to keep things separated between logic and view code. This also has the neat advantage of enabling us to work on pure logic without launching the full App.

Network Layer

Our Network Layer is hidden behind an Api interface. That means our View controllers have no idea about our networking library. That also means we could switch our api implementation to return dummy data for testing purposes, without having to touch a single line of our controllers \o/.

Image Loading and Cache 🖼

We use Kingfisher for async loading of our images and cache handling. The api is simple yet very customizable. We were previously using AlamofireImage but switched to Kingfisher for performance reasons.

Networking ☁️

For networking we use ws ☁️ which is a simple promise-based JSON networking library.

It has the advantage of packing 3 things:

This neat layer of abstraction enables us to add and maintain routes efficiently.

Async 🕐

We rely heavily on Promises to keep our asynchrounous code clean and maintainable. For that, we use then 🎬

JSON Parsing ⚙️

We had strong requirements for our JSON parsing library: It should not force us to subclass our Models, support both Classes and structs, and be as simple as possible. For that we use Arrow 🏹, it takes care of all the boilerplate JSON parsing code for us and keep model mappings clean and maintainable.

Layout 🏝

We do not use Storyboards nor Xibs for reasons that we will no elaborate here. TLDR : It’s easier to maintain. You can find a great article on that matter here.

Yes, all of our views and TableView Cells are in code ! And this brought up great benefits!

As you may know though, pure Autolayout code is quite verbose and that’s why we use Stevia🍃 for keeping it readable and maintainable.

Wait but coding views is code is slow isn’t it ?!

Well code injection 💉 thanks to injectionForXcode enables us to code views faster than ever!

“Shy” Navigation Bar 🙈

For an immersive feed with the navigation bar hiding on scroll we use andreamazz’s AMScrollingNavbar implementation.

Image Picker & Filters 📸

Concerning media capture, we had quite a few requirements.

We wanted a solution that is full Swift, supports photo , video , library , square crop and filters! Unsurprisingly we had to write our own. For that, we rolled out our own version of Fusuma heavily inspired on Instagram design, which you can grab here

Deployment 🚀

Continuous Integration 🤖

Bitrise clearly is the best thing that happens to us. Making a new build went from 2 hours to literally a minute! We use it to run unit tests everyday. And pushing on “staging” branch automatically triggers a TestFlight build. Less time making builds = more time coding \o/. Plus it has all the benefits of continuous integration, such as making sure the app builds on a fresh machine.

TestFlight ✈️

We use Testfilght for sharing builds with our internal and beta testers. Yes there are tons of alternatives out there but most of the time, we try to be good Apple citizens and use the Apple tool. The most annoying thing about Testflight is that a build can sometimes hang between half an hour and 4 hours before being delivered to testers with no apparent reason. The awesome part is that it’s fully integrated with iTunes connect and keeps things simple.

Git flow 🐙

Our git flow is pretty standard we develop features on a feature branch say “filters” then merge it on “dev”. Once finished we test the results by merging on “staging”, which automatically triggers the TestFlight deployment. Once approved by Apple, we merge “s_taging_” into “master”.

Tools 🛠

Dependency Manager 🕸

Carthage is our preferred way for dependency management. Less known than Cocoapods, but since all of our choices are driven by simplicity , Carthage was the way to go.

Code linting

We use SwiftLint to keep our codebase clean and consistent.

Localisation 🏁

We use Localize, It keeps our localization files clean and sorted alphabetically. It checks for missing, untranslated and unused keys thus allows for a stress-free localization of the App.

We use Laurine to generate type-safe structs from our Localization.string files. Using a dot syntax like “UserValidation.Popup.Title” now generates a nice namespaced struct. On top of the sweet autocompletion , the compiler now breaks if a translation key is missing!

Assets safety net 👮

In an world where design trends change every year, we needed a way to guard against missing assets. While solutions like Misen or SwiftGen are great, they generate extra swift structs and moves us aways from Apple solution aka image literals. They solve one issue: code breaks when asset disappears, because the corresponding struct does as well.

That’s exactly what AssetChecker 👮 does while enabling us to use the great and very readable image literals 😃 Plus it warns when an Asset is not used in the code, great for cleaning a long lasting project.

Push Notifications 📲

Coming from Parse Push (RIP) we looked carefully for an alternative solution. We chose Batch and are very happy with it. Their UI is super simple and their segmentation tool oh so powerful. Automatic campaigns are also fantastic for combatting retention \o/

AB Testing ⚗️

Optimizely enables us to test out ideas in a data driven way.

Crash Reporting 🐞

Crashlytics (now part of Fabric) is our tool of choice for tracking crashes.

Analytics 📈

Google analytics is our monster for analytics but we tend to use Fabric more and more since it delivers a bite-sized analytics that covers most of the basic needs, DNU, DAU, MAU etc.

Deep Linking 🔗

Detecting where someone comes from even before they actually install the App is pretty Magic. For that we use Branch solution.

And that’s pretty much it! Enjoy 😃


More goodness ❤️

Swift — Write Concise Networking Code with WS☁️

Swift — Write beautiful Async code, with Promises

Swift — Parse JSON like a boss


Original article published here

Discover and read more posts from Sacha Durand Saint Omer
get started