Moya Tutorial for iOS: Getting Started

Moya is a networking library inspired by the concept of encapsulating network requests in type-safe way, typically using enumerations, that provides confidence when working with your network layer. Become a networking superhero with Moya! By Shai Mishali.

Leave a rating/review
Download materials
Save for later
Share
Note: This tutorial uses Xcode 10 and Swift 4.2. The libraries it depends upon are not yet updated for Swift 4.2 but can be used without issue. You’ll need to ignore the single warning telling you that Swift 4.2 conversion is available.

There are many moving pieces involved in crafting a beautiful and performant iOS app. One of the most important pieces, if not the most important for a modern app, is networking. As an iOS developer, you may structure your networking layer in many different ways — be it using URLSession or some third-party library.

In this tutorial, you’ll learn about a third-party networking library named Moya, which aims to create a type-safe structure to your network services and requests.

You might ask yourself, “What is this Moya? I already know and love Alamofire!” And if you don’t know and love it, now would be a great time to check out our awesome tutorial on this subject.

Well, this is the great part: Moya actually uses Alamofire while providing a different approach to structuring your network layer. You’ll learn much more about the relation between Moya and Alamofire later in this tutorial.

In this tutorial, you’ll build a neat little app called ComicCards in which you’ll use the Marvel API to show the user a list of comics released in a given week, along with their cover images and other interesting information. When a user selects a comic, your app will generate an image of a shareable card with the comic’s information and image, letting the user upload it to the Imgur service and share it:

The finished ComicCards app!

The finished ComicCards app!

The finished ComicCards app!

Woah — two different API services in one app? Don’t worry! It isn’t as hard as it sounds. Let’s get started!

Note: This tutorial assumes basic knowledge of how HTTP APIs work, though you should be able to easily follow this tutorial even with minimal knowledge. But if you want to know more about HTTP APIs, either refer to the previously mentioned Alamofire tutorial, or refer to this interesting site for more information on REST API basics.

Getting Started

Use the Download Materials button at the top or bottom of this tutorial to download the ComicCards starter project, which already has Moya bundled. Open ComicCards.xcworkspace and not the project file — this is important.

With the project open, check out Main.storyboard to get a general sense of the app structure:

The ComicCards app consists of two different screens:

  • ComicsViewController: The view controller responsible for presenting the list of comics to the user.
  • CardViewController: The view controller responsible for creating the card for the selected comic and letting the user share the generated card.

Build and run the project. You should see the following screen:

Unsurprisingly, you’re presented with an error screen since you haven’t yet implemented the logic related to fetching the comics from the server and displaying them in your app. You’ll get to adding all of the required code very soon, but first you need to learn a bit about Moya.

Moya: What Is It?

What Is Moya?

Moya is a networking library focused on encapsulating network requests in a type-safe way, typically by using enumerations (e.g., enum) to provide compile-time guarantees and confidence when working with your network layer, along with added discoverability.

It was built by Ash Furrow and Orta Therox for Artsy’s Eidolon app and quickly gained popularity. Today, it’s entirely maintained by a passionate community of open-source contributors.

How Is Moya Related to Alamofire?

As mentioned in the introduction to this tutorial, Moya and Alamofire are tightly related simply by the fact that Moya doesn’t really do any networking by itself. It uses Alamofire’s battle-tested networking capabilities and simply provides additional abilities, types and concepts to further abstract Alamofire.

Practically speaking, you are using Alamofire! Instead of using it directly, you use Moya, which uses Alamofire under the hood.

Looking at the starter project’s Podfile.lock reveals just that — Alamofire is a dependency of Moya:

Moya’s Building Blocks

Moya introduces a few unique concepts and building blocks that you should be aware of before starting to write your code. It uses the following building blocks to let you describe your entire networking chain:

Moya’s Building Blocks

Moya's Building Blocks

Moya’s Building Blocks

  • Provider: Moya’s MoyaProvider will be the main object that you’ll create and use when interacting with any network service. It’s a generic object that takes a Moya Target upon initialization.
  • Target: A Moya target usually describes an entire API service; in this case, a Marvel target and an Imgur target. Each of these targets describe the service, its possible endpoints, and the information required by each endpoint to perform a request. You define a target by conforming to the TargetType protocol.
  • Endpoint: Moya uses the semi-internal Endpoint object to describe the basic pieces of information required to perform a network request, e.g., HTTP method, request body, headers and more. Moya’s MoyaProvider transforms every target to an Endpoint, which is eventually transformed into a raw URLRequest. Endpoints are highly customizable but are out of scope for this tutorial as you won’t need any custom mappings.

Now that you have all of the basic theory out of the way, it’s time for you to write some code!

Marvel API – The API of Heroes

The Marvel API is the world’s largest comic API, created and maintained by Marvel itself.

Start by creating a free account. Once you’re all set, go back to to the My Developer Account page where you’ll find your new public and private keys:

Marvel API Keys

Keep both keys handy; you’ll need them in a few minutes.

Creating Your First Moya Target

Go back to the ComicCards Xcode project. In your project navigator, right-click the ComicCards/Network folder and select New File… Create a new Swift file and name it Marvel.swift:

After import Foundation, add the following code:

import Moya

public enum Marvel {
  // 1
  static private let publicKey = "YOUR PUBLIC KEY"
  static private let privateKey = "YOUR PRIVATE KEY"

  // 2
  case comics
}

You just created a very simple enumeration describing the API service that you’re going to use:

  1. These are your Marvel public and private keys. You store them alongside the definition of your service to make sure the keys are easily accessible as part of your service configuration. Make sure to replace the placeholders with the actual keys generated in the previous step.
  2. A single enumeration case named comics, which represents the only endpoint you’re going to hit in Marvel’s API — GET /v1/public/comics.

Now that you have your basic enumeration configured, it’s time to actually make it a target by conforming to TargetType.

Add the following code to the end of the file (after the closing curly bracket):

extension Marvel: TargetType {
  // 1
  public var baseURL: URL {
    return URL(string: "https://gateway.marvel.com/v1/public")!
  }

  // 2
  public var path: String {
    switch self {
    case .comics: return "/comics"
    }
  }

  // 3
  public var method: Moya.Method {
    switch self {
    case .comics: return .get
    }
  }

  // 4
  public var sampleData: Data {
    return Data()
  }

  // 5
  public var task: Task {
    return .requestPlain // TODO
  }

  // 6
  public var headers: [String: String]? {
    return ["Content-Type": "application/json"]
  }

  // 7
  public var validationType: ValidationType {
    return .successCodes
  }
}

This might seem like a ton of code, but it’s all simply to conform to TargetType. Let’s break this down:

  1. Every target (e.g., a service) requires a base URL. Moya will use this to eventually build the correct Endpoint object.
  2. For every case of your target, you need to define the exact path you’ll want to hit, relative to the base URL. Since the comic’s API is at https://gateway.marvel.com/v1/public/comics, the value here is simply /comics.
  3. You need to provide the correct HTTP method for every case of your target. Here, .get is what you want.
  4. sampleData is used to provide a mocked/stubbed version of your API for testing. In your case, you might want to return a fake response with just one or two comics. When creating unit tests, Moya can return this “fake” response to you instead of reaching out to the network. As you won’t be doing unit tests for this tutorial, you return an empty Data object.
  5. task is probably the most important property of the bunch. You’re expected to return a Task enumeration case for every endpoint you want to use. There are many options for tasks you could use, e.g., plain request, data request, parameters request, upload request and many more. This is currently marked as “to do” since you’ll deal with this in the next section.
  6. headers is where you return the appropriate HTTP headers for every endpoint of your target. Since all the Marvel API endpoints return a JSON response, you can safely use a Content-Type: application/json header for all endpoints.
  7. validationType is used to provide your definition of a successful API request. There are many options available and, in your case, you’ll simply use .successCodes which means a request will be deemed successful if its HTTP code is between 200 and 299.
Note: Notice that you’re using a switch statement in all of your properties even though you only have a single case (.comics). This is a general best practice, since your target might easily evolve and add more endpoints. Any new endpoint will require its own values for the different target properties.

Wow, that was a lot of knowledge to take in! You should feel very proud given the fact that this is most of what you need to know to work with Moya in its most basic form!

There’s only one thing missing in your new Marvel target — the “to do” left in the code, meaning the returned Task.