View Controllers, Screens, Modals

In this chapter we are going to learn how to create basic user interfaces (UI) We will start with UIViewControllers or Screens.

In Objective-C we use UIViewControllers. This is a controller from an MVC architecture - it connects views with models. UIViewController includes the main view of the screen, where you will put all your buttons, labels, table views and other views.

ProMotion gem that we have added earlier replace term UIViewController with Screens. It is easier to understand because UIViewController is just a single screen of the application. Promotion's Screen is just a UIViewController with Ruby syntax (or its subclass). Instead of viewDidLoad delegate method, you can use shorter and prettier on_load. Instead of viewWillAppear, you can use will_appear, etc.

There are lots of screen (UIViewController) types. Here is a small review of most important ones.

UIViewController

Plain UIViewController or Screen is just a white canvas where we can add UI elements. You can use it to create any type of screens you want, including Table Views and Collection Views.

UITableViewController

UITableViewController is a full-screen table. A good example of a table screen is an Apple's default address book app or settings app. Here is how plain table screen looks like:

UICollectionViewController

UICollectionViewController is a full-screen collection of objects. If the table is always a vertical list of elements, collection views' layout can be customized. Good example of a collection screen is an Apple's Photos app:

UITableViewController and UICollectionViewController are actually plain screens with table view or collection view inside. They were made to save developers some time when they are working with this type of screens. It means that you can always use a blank screen, and put a table or collection view inside, and make it full screen. Even though UITableViewController and UICollectionViewController save some time in the beginning, they may need more time for customization in the future. These type of screens are not that easy to customize as a UIViewController with collection or table inside.

UITableViewController and UICollectionViewController will save you some code, but if you want your screens look a little bit different, you won't be able to modify them. These type of screens won't allow you to add some kind of toolbar to it, or you won't be able to change table or collection view size - it has to be always full screen, etc.

In this book, we will always use plain UIViewController (or Screen, which is the same). If we will need a table or a collection, we will create them manually, and will insert into the screen. It will take about ~10 additional lines of code, but you will be able to customize it to your needs at any moment.

Practice

Let's create our first Screen. To do it, create a new file in /app/screens. I am going to name it home_screen.rb, but you can use whatever name you want. It would be a good idea to give files names same as a class name that will be described inside.

In our new /app/screens/home_screen.rb we are going to create a HomeScreen class. It will be based on a plain PM::Screen. PM here stands for ProMotion. To be sure that it is our screen will be shown, let's change its color to yellow. To do it, we will need to get the main view of our screen, and change its backgroundColor property.

To start customizing screen, we need to figure out the best time when we want to do it. As with App Delegate, screens have delegates methods that are called at particular times. In these methods, we can add our code to setup UI, add some business logic, communicate with models, etc. Here is example of some methods:

You can read more on them in Promotion Screen Docs.

I'm going to use on_load method to change the background color. on_load is a good place to start working on the UI - main view has been created, and we can start to configure the screen.

        class HomeScreen < PM::Screen
          def on_load
            self.view.backgroundColor = UIColor.yellowColor
          end
        end
      

As you can see, we have created a HomeScreen that is based on a Promotion's Screen class. We have to use it as a base class because otherwise the app will not know that this is a Screen, and not a Model or Layout, for example. Also, base class provides us with lots of useful methods.

Then inside of on_load method that called when the main view of a screen is loaded, we are changing the main view color to yellow. To tell our app that we need to alter the color of this particular screen, we need to get an object of a screen first. It is done with keyword self. Then we are getting this screen's view with view method. And only then we can change the background color to whatever we want.

Even though the screen has been created, we still need to show it right when our app loads. To do it, we need to go to out App Delegate, and tell it to open the HomeScreen when app is ready:

        class AppDelegate < PM::Delegate
          def on_load(app, options={})
            open HomeScreen.new
          end
        end
      
We could also create an instance of HomeScreen first, and then open it. There will be absolutely no difference between these two parts of code:
        class AppDelegate < PM::Delegate
          def on_load(app, options={})
            screen = HomeScreen.new
            open screen
          end
        end
      
Let's launch the app with rake now:

To open our screen, we used command open. This command opens the screen as a next main screen. However, sometimes you may want to open a temporary screen, to show the user some info, and close it after. These type of screens are usually used for some kind of small dialogs and called modal screens. Modal screens are child screens, which means they can be shown only from another (parent) screen

Let's try to open second Home Screen modally, right after the first one has been shown. To do it, we will need to use an open_modal command. By default modal windows slide from the bottom of the screen and take the whole screen. Except showing a new screen modally, we will also change its color to red:

        class AppDelegate < PM::Delegate
          def on_load(app, options={})
            screen = HomeScreen.new
            open screen

            modal_screen = HomeScreen.new
            modal_screen.view.backgroundColor = UIColor.redColor
            screen.open_modal modal_screen
          end
        end
      
Here we created a new instance of a HomeScreen and changed its color to red. Earlier we used the word self to get an instance of a screen, but here we already have a variable with this screen, so we can use it instead. Then we used our first screen to open the second screen modally from it. Try to use rake command to launch an app. You will see how the second, red screen slides from the bottom to the top and hides the first screen.

On iPads, we can make modal screens look smaller. But first, let's check how does modal screen works on iPad:

rake device_name="iPad Air"

Right now iOS thinks that the application is made for iPhones only, and it tries to show it in iPhone-like dimensions. iPad support can be quickly added in Rakefile's device_family property. By default, it is set to iPhone only, and we are going to add iPad:

        app.device_family = [ :iphone, :ipad ]
      
Now when we launch the app on iPad, it will work as expected:

To change the way modal screen shown on iPads, we need to pass a presentation_style property, set to UIModalPresentationFormSheet. In addition we need to add a navigation bar to the screen with nav_bar: true:

        modal_screen = HomeScreen.new nav_bar: true,
          presentation_style: UIModalPresentationFormSheet
        modal_screen.view.backgroundColor = UIColor.redColor
        screen.open_modal modal_screen
      
When you launch the app next time, you will see a smaller modal screen shown on top of your main yellow HomeScreen:

This is it for now! We learned how to create and open new screens, saw different screen types ( UITableViewController and UICollectionViewController ), and now we are ready to add some user interface elements to our screens.

Book Index | Next