RxSwift: Transforming Operators in Practice

Learn how to work with transforming operators in RxSwift, in the context of a real app, in this tutorial taken from our latest book, RxSwift: Reactive Programming With Swift! By Marin Todorov.

Leave a rating/review
Save for later
Share

In the previous tutorial on transforming operators, you learned about the real workhorses behind reactive programming with RxSwift: the map and flatMap dynamic duo.

Of course, those aren’t the only two operators you can use to transform observables, but a program can rarely do without using those two at least few times. The more experience you gain with these two, the better (and shorter) your code will be.

In that previous tutorial (which is also based on a chapter from our RxSwift book) you already got to play around with transforming operators in the safety of a Swift playground. Hopefully you’re ready to take on a real-life project! You’ll get a starter project, which includes as much non-Rx code as possible, and you will complete that project by working through a series of tasks. In the process, you will learn more about map and flatMap, and in which situations you should use them in your code.

Note: In this tutorial, you will need to understand the basics of transforming operators in RxSwift. If you haven’t worked through the previous tutorial, “RxSwift: Transforming Operators”, do that first and then come back to this tutorial.

Without further ado, it’s time to get this show started!

Getting Started With GitFeed

Download the starter project for this tutorial here. The project is up to date with Xcode 8.2.1 and RxSwift 3.2.

I wonder what the latest activity is on the RxSwift repository? In this tutorial, you’ll build a project to tell you this exact thing.

The project you are going to work on in this tutorial displays the activity of a GitHub repository, such as all the latest likes, forks, or comments. To get started with GitFeed, open the starter project for this tutorial, install the required CocoaPods, and open GitFeed.xcworkspace.

The app is a simple navigation controller project and features a single table view controller in which you will display the latest activity fetched from GitHub’s JSON API.

Note: The starter project is set to display the activity of https://github.com/ReactiveX/RxSwift, but if you’d like to change it to any other repository of your choice, feel free.

Run the app and you will see the empty default screen:

There’s nothing too complex going on right now, but you’ll soon have this whole setup ablaze! :]

The project will feature two distinct storylines:

  • The main plot is about reaching out to GitHub’s JSON API, receiving the JSON response, and ultimately converting it into a collection of objects.
  • The subplot is persisting the fetched objects to the disk and displaying them in the table before the “fresh” list of activity events is fetched from the server.

You will see that these two complement each other perfectly — and there are plenty of opportunities to use both map and flatMap to build what’s required.

Fetching Data From the Web

Hopefully you’ve used the URLSession API before and have a general idea of its workflow. In summary: you create a URLRequest containing a web URL and parameters, then send it off to the Internet. After a bit, you receive the server response. In this tutorial, to use URLSession the Rx way, you will simply use a solution boxed with RxCocoa — RxSwift’s companion library.

If you peek into GitFeed’s Podfile, you will notice that you import two different CocoaPods: RxSwift and RxCocoa. What gives?

RxCocoa is a library based on RxSwift, which implements many helpful APIs to aid with developing against RxSwift on Apple’s platforms. In an effort to keep RxSwift itself as close as possible to the common Rx API shared between all implementations such as RxJS, RxJava, and RxPython, all “extra functionality” is separated into RxCocoa.

You will use the default RxCocoa URLSession extension to quickly fetch JSON from GitHub’s API in this tutorial.

Using map to Build a Request

The first task you will undertake is to build a URLRequest you will send off to GitHub’s server. You will follow a reactive approach that might not make sense immediately, but don’t worry — when you re-visit that part of the project later on, you will appreciate it!

Open ActivityController.swift and peek inside. You configure the view controller’s UI in viewDidLoad(), and when you’re finished, you call refresh(). refresh() in turn calls fetchEvents(repo:) and hands over to it the repo name "ReactiveX/RxSwift".

It is in fetchEvents(repo:) where you will add most of your code in this section. To get started, add the following:

let response = Observable.from([repo])

To start building the web request, you begin with a simple string, which is the repository’s full name. The idea to start with a string instead of directly building a URLRequest is to be flexible with the observable’s input.

Next, take the address string and create the fully qualified URL of the activity API endpoint:

.map { urlString -> URL in
  return URL(string: "https://api.github.com/repos/\(urlString)/events")!
}

You use a couple of shortcuts to create the full URL by using a hard-coded string and force unwrapping the result. You end up with the URL to access the latest events’ JSON.

Have you noticed that you specified the closure’s output type? Did you really have to do that? The obvious answer is no; usually you don’t need to explicitly spell out closure input and output types. You can usually leave it to the compiler to figure those out.

However, especially in code where you have several map and/or flatMap operators chained together, you might need to help the compiler out. It will sometimes get lost in figuring out the proper types, but you can aid it by at least spelling out the output types. If you see an error about mismatched or missing types, you can add more type information to your closures and it’ll probably fix the problem.

But enough about compiler woes — back to coding!

Now that you have a URL, you can move on to transforming it into a complete request. Chain to the last operator:

.map { url -> URLRequest in
  return URLRequest(url: url)
}

Easy enough: you use map to transform a URL to a URLRequest by using the provided web address.

Nice work! You’ve chained a couple of map operators to create a more complex transformation:

Now it’s time to bring flatMap into play and fetch some JSON.