Rewriting an app in Swift, part 2

Joel Márquez
6 min readJan 4, 2018

--

Hello guys and welcome to the second part of this series of posts where I’ll show to you how I’m rewriting Todo Rugby on Swift.

On the first part I showed you how I built up the skeleton programmatically, with Drawer, Tabs, and the NavigationManager .

In this one, I’ll cover the following points:

  • Networking: Using Moya to write your service layer, among with the brand new Codable protocol, a cool feature of Swift 4.
  • Base Classes: Why you should consider using them.
  • Equatable: How to implement your old isEqual in the Swift way.
  • guard let : your battle knife for all your Optional problems.

Networking

Moya

A very important piece of any app that handles data from an API is the Networking layer. Reading and investigating the best tools and Pods available out there, I step up with Moya, a network abstraction layer that under the hood uses Alamofire (the successor of AFNetworking for Swift). One of the cool things of this framework is that you don’t have to rewrite a new networking client each time you start a new app. It handles that internally. The only things that you have to specify are:

  • Enums: All of your requests will be defined in an enum, with their parameters and additional data.
  • Base URL: The url for accessing your API.
  • Endpoints: With each new enum, you’ll have to tell them which is the associated endpoint to that enum, and how it should handle the parameters on that endpoint.
  • Method: The HTTP verb that it should use for each enum value (.get , .post , etc.).
  • Task: Whether the request should be plain or have additional data (query string params, form data, multi part, etc.).
  • Headers: Which headers should you use for each endpoint.
  • Sample data: Because yes, it lets you mock an endpoint if you provide it.

Before setting up the navigation with the Drawer and Tabs, a thing that I always like to do is to have the control of an update, and if that update should be forced or not. This is, if the user can still use the app regarding the update or if the only way to use it is by updating it. I’m not covering how to write your force update logic, but the first endpoint that I’ll cover is the version one.

After implementing our Service enum conforming the TargetType protocol, you should have something like this:

And the way you should call it is this:

As you can see, you tell them how to handle your endpoints, and they give you a strong typed framework for handling all your HTTP requests. ¡Bravissimo!

Codable

The Codable protocol and the JSONDecoder class are both new features of Swift 4. They allow you to write pure structs that matches your JSON data, and then they decode it so you can use that structs on your app. How? Like this:

Ok but how should I decode my JSON into that struct? Thanks to Moya developers, they introduced an easy way to handle this decoding directly on the result of your request:

And that’s it. If you defined correctly the properties of your struct (both name and type), the map method (it uses the JSONDecoder inside it) should decode the response into your struct, so then you could use it later.

For more info about how the JSONDecoder class handles the structs and its keys you should watch this video, from minute 24.

Base Classes

Inheritance is a powerful tool of OOP, and you should always try to take advantage of it. On iOS (and in this case, on Swift), I like to have this base classes:

BaseViewController

It inherits from UIViewController and has handy methods for dealing with the NavBar setup, screen tracking and a couple of things more.

BaseTableViewCell

As you could imagine, it inherits from UITableViewCell and has very useful methods. It also has is a model property, which is a struct that implements the Decodable protocol. It looks like this:

As you can see, a class that inherits from this one should implement the setupCell() method to populate the components of the cell with the ones from the struct, and then you should do something like this:

And the last part of this is implementing the setupCell() on the TournamentTableViewCell class:

In this way, it keeps your code as simple as possible. The setupCell() method will be called when the cell.model = tournament is executed.

BaseViewModel

The last one but not the less important, in this Swift version of the app, I’ve added this new base class. It’s a container of a Codable value (whether is a single struct or an array of structs), and has a method that fetches an endpoint and tries to map the response to it’s specified value. Ladies and gentleman, here it is:

One important thing to notice here is that I used ReactiveSwift (the successor of the best reactive framework for Objective-C, ReactiveCocoa). I preferred to use this one instead of RxSwift because the public API is almost the same than the previous version, so it would be easy to get used to it. It’s main parts are:

  • A value property which could be an array of Codable ‘s, or a single Codable .
  • The fetchData method returns a SignalProducer (the old RACSignal) which in case of success it’s output will be the value , and in case of failure it will be the error.
  • If the class that inherits from it wants to know when the value is set, it has to override the valueDidSet method and that’s all.

Let’s see how to implement our VersionViewModel :

Easy as cake! It’s worth to mention that if you want to unit test your view model, you could do something like this:

With this, when calling fetchData , it will return the sample data you provided for that endpoint.

Equatable

Probably you’ve never implemented the isEqual method. I think one of the reasons for that is because it took this amount of code:

The isEqualToTournament is a handy method like isEqualToString or isEqualToNumber , knowing that the receiver is from the same class, you’d probably use this one. But if you want to sort lists or make operations with sets that under the hood use the isEqual , you’ll have to implement it.

With Swift we have an amazing feature called operator overloading (if you coded on C++ you’d probably know what I’m talking about). Basically, you can override operators to do custom actions with your objects. On this case, we’ll override the == operator so we can check if two objects are equal using it:

Amazing! Now each time you write a == comparison between two tournaments, it’ll use this operator and internally check for their ID’s.

guard let

The last thing that I’m going to talk on this post is about returning early, a coding style that checks and returns for invalid cases, and lets you focus on the code that actually will be executed on your method.

On Swift we have Optionals, which are an amazing and safe feature that let’s you check if a property has or not a value set. Given that, they have given us a way to return early for those cases, using guard let :

As you can see, I’m checking for two Optional values here on the same line. Once the first check passes, the team becomes available as Non-Optional, and then the logoURL statement creates also a Non-Optional value that lets me continue with the method. Pretty cool right? Here you have a post where they explain how to make more complex guard let checks.

We reached the end of this post. I’ve covered 4 important parts of Swift, it’s ecosystem, and a bunch of practices that they will allow you to write better apps. I’ll keep posting here as I’m continuing with this rewriting.

Please leave a comment with your thoughts, doubts or suggestions so we all can learn from sharing the experience of developing an app with Swift.

Cheers!

--

--

Joel Márquez

📱Software Manager @mercadolibre.arg 🏉 Co-Founder of @todorugby.app 📍Haedo, Bs.As., Argentina