Skip to content

iOS Tutorial 1

Tuomas Artman edited this page Jan 31, 2018 · 22 revisions

Create your first RIB

Welcome to the tutorials, which have been designed to give you a hands-on walkthrough through the core concepts of RIBs. As part of the tutorials, you'll be building a simple TicTacToe game using the RIBs architecture and associated tooling.

We've provided you with a project that contains the boilerplate for a new RIBs application. You can find the source files here. Follow the README to install and open the project before reading any further.

Goal

The goal of this tutorial is to understand the various pieces of a RIB, and more importantly, how they interact and communicate with each other. At the end of this tutorial, we should have an app that launches into a screen where the user can type in player names and tap on a login button. Tapping the button should then print player names to the Xcode console.

Create LoggedOut RIB

Select New File menu item on the LoggedOut group.

Select the Xcode RIB templates.

Name the new RIB "LoggedOut" and check the "Owns corresponding view" checkbox.

We want a view for the LoggedOut RIB, since it we'll want to be able to display a "Sign Up" button and text fields to query for the player names.

Create the files and make sure it’s added to the "TicTacToe" target and saved into the "LoggedOut" folder.

Now we can delete the DELETE_ME.swift file. It was only temporarily needed so the project would compile without the LoggedOut RIB we just created.

Understanding generated code

image7

We just generated all the classes for a the LoggedOut RIB.

  • The LoggedOutBuilder conforms to LoggedOutBuildable so other RIBs that uses the builder can use a mocked instance that conforms to the buildable protocol.
  • The LoggedOutInteractor uses the protocol LoggedOutRouting to communicate with its router. This is based on the dependency inversion principle where the interactor declares what it needs, and some other unit, in this case, the LoggedOutRouter, provides the implementation. Similar to the buildable protocol, this allows the interactor to be unit tested. LoggedOutPresentable is the same concept that allows the interactor to communicate with the view controller.
  • The LoggedOutRouter declares what it needs in LoggedOutInteractable to communicate with its interactor. It uses the LoggedOutViewControllable to communicate with the view controller.
  • The LoggedOutViewController uses LoggedOutPresentableListener to communicate with its interactor following the same dependency inversion principle.

LoggedOut UI

Below is the UI we want to build, so we'll need to modify the LoggedOutViewController. To save time, you can also use our code and add it to the LoggedInViewController implementation.

Make sure to import SnapKit in the LoggedOutViewController if you're using the provided example code so that the project compiles.

Login Logic

The LoggedOutViewController calls to its listener, LoggedOutPresentableListener, to perform the business logic of login, passing in the names of player 1 and 2.

Modify the LoggedOutPresentableListener protocol in the LoggedOutViewController.swift file to be the following:

protocol LoggedOutPresentableListener: class {
    func login(withPlayer1Name player1Name: String?, player2Name: String?)
}

Notice that both player names are optional, since the user may not enter anything for the player names. We could disable the Login button until both names are entered, but for this exercise, we’ll let the LoggedOutInteractor deal with the business logic of handling nil names. If player names are empty, we'll want to default them to "Player 1" and "Player 2" in the implementation.

Next, we'll modify LoggedOutInteractor to conform to the modified LoggedOutPresentableListener protocol, by adding the following methods:

// MARK: - LoggedOutPresentableListener

func login(withPlayer1Name player1Name: String?, player2Name: String?) {
    let player1NameWithDefault = playerName(player1Name, withDefaultName: "Player 1")
    let player2NameWithDefault = playerName(player2Name, withDefaultName: "Player 2")

    listener?.didLogin(withPlayer1Name: player1NameWithDefault, player2Name: player2NameWithDefault)
}

private func playerName(_ name: String?, withDefaultName defaultName: String) -> String {
    if let name = name {
        return name.isEmpty ? defaultName : name
    } else {
        return defaultName
    }
}

For now, when the user logs in, we'll just print out the user names.

Finally, we'll hook up our ViewController to call the listener method when the login-button is pressed. In LoggedOutViewController.swift, change the didTapLoginButton method (in case you used our UI code) to the following implementation:

@objc private func didTapLoginButton() {
    listener?.login(withPlayer1Name: player1Field?.text, player2Name: player2Field?.text)
}

Tutorial complete

Congratulations! You just created your first RIB. Now onwards to tutorial 2.

Once you've read through the documentation, learn the core concepts of RIBs by running through the tutorials and use RIBs more efficiently with the platform-specific tooling we've built.

Tutorial 1

iOS, Android

Tutorial 2

iOS, Android

Tutorial 3

iOS, Android

Tutorial 4

iOS, Android

Tooling

iOS, Android

Clone this wiki locally