iOS From Scratch With Swift: First Steps With UIKit

UIKit is the framework that you'll user most often when developing iOS applications. It defines the core components of an iOS application, from labels and buttons to table views and navigation controllers. In this article, not only will we start our exploration of the UIKit framework, we will also explore the internals of an iOS project and the basic building blocks of iOS applications.

What Is the UIKit Framework?

While the Foundation framework defines classes, protocols, and functions for both iOS and OS X development, the UIKit framework is exclusively geared towards iOS development. It's the equivalent of the Application Kit or AppKit framework for OS X development.

Like Foundation, UIKit defines classes, protocols, functions, data types, and constants. It also adds additional functionality to various Foundation classes, such as NSObjectNSString, and NSValue through the use of Objective-C categories.

Objective-C categories are a convenient way to add extra methods to existing classes without the need for subclassing. They are similar to Swift extensions. Read this tutorial by Aaron Crabtree if you want to learn more about Objective-C categories.

Instead of exploring the key classes of UIKit, like we did for the Foundation framework, we're going to create and journey through a new iOS project, exploring the classes we encounter. By taking this approach, it will quickly become clear in what context a class is used, how each class fits into the broader scheme of an iOS application, and what role it plays.

A New Beginning

Launch Xcode and create a new project by selecting New > Project... from the File menu. In the iOS section on the left, select the Application category. From the list of project templates, choose the Single View Application template.

The Single View Application template contains the basic building blocks of an iOS application, which makes it a good place to start our journey.

Choosing a Project Template

Name the project FirstSteps and enter an organization name and identifier. Set Language to Swift and set Devices to iPhone. Leave the checkboxes at the bottom unchecked.

Configuring the Project

Tell Xcode where you want to save the new project and make sure to put the project under version control by checking the checkbox labeled Create Git repository on My Mac. Revisit this article for more information about version control and its benefits.

Saving the Project

Files and Folders

We have learned quite a few new things since the last time we created an iOS project from scratch so it's a good idea to explore the various files and folders of our new project to see if they ring a bell.

In the Project Navigator, you should see two folders at the root of the project:

  • Products
  • a folder with your project's name, FirstSteps in this example

Let's take a look at the contents of each of these folders.

Project Structure

Products

The Products folder currently contains one item. It bears the name of the project and has an extension of .app. The Products folder contains the application—or applications—created by the project after compilation of the source code.

Have you noticed that FirstSteps.app is highlighted in red? Whenever Xcode is unable to locate a file, it highlights the file in red. Don't worry, though. Because the project hasn't been compiled yet, Xcode hasn't created the product yet.

Project Folder

Most of your time is spent in the project folder, which currently contains six files. The first two files, AppDelegate.swift and ViewController.swift, are source files. These files contain the source code of the application.

Main.storyboard contains the user interface of the application. We've already worked with storyboards earlier in this series. Notice that there's a second storyboard, LaunchScreen.storyboard. This storyboard is used by the operating system when the application is being launched. Instead of showing an empty view, the operating system uses this storyboard to dynamically create a launch image, which is shown to the user when the application is loading.

Info.plist, commonly referred to as the "info-dot-plist" file of a project, is a property list that contains various configuration settings. Most of these settings can also be modified by selecting the project in the Project Navigator, choosing the target in the Targets list, and opening the GeneralCapabilities, and Info tabs.

Assets.xcassets is a special type of folder for storing your project's assets, such as images.

Application Components

Now that we know what the different files and folders in our project are for, it's time to explore the different components of an iOS application. As we continue our journey, we will come across several classes that belong to UIKit. Each class that belongs to the UIKit framework starts with the class prefix UI. Remember that Foundation classes are prefixed with NS.

The Model-View-Controller Pattern

Before we start exploring the UIKit framework, I want to talk about the Model-View-Controller (MVC) pattern. The MVC pattern is one of the most widespread patterns in object-oriented programming. It promotes code reusability and has close ties with the concept of separation of responsibilities or concerns. One of the main objectives of the MVC pattern is the separation of an application's business logic from the presentation layer.

Cocoa Touch embraces the MVC pattern, which means it's important to understand what it is and how it works. In other words, by understanding the MVC pattern, it will be much easier to grasp how the different components of an iOS application work together.

In the MVC pattern, the model layer is in control of the business logic of an application. Interacting with a database, for example, is the responsibility of the model layer. The view layer presents the data that is managed by the model layer to the user. The view layer manages the user interface and user input.

The controller is the glue between the model layer and the view layer. While the model layer and the view layer don't know about each other's existence, the controller knows about both.

Because the controller knows about model and view, it's often the least reusable piece of an application. The less an object knows about its environment and the objects it interacts with, the easier it is to reuse.

UIApplication

Even though the UIApplication class is a key component of every iOS application, you won't interact with it very often and you will rarely, if ever, feel the need to subclass UIApplication.

When an application launches, a singleton of this class is created. Do you remember what a singleton object is? It means that only one object instance of the UIApplication class is created during an application's lifetime.

The UIApplication instance is the entry point for user interaction and it dispatches events to the appropriate target objects. The exact meaning of this will become clear in a few minutes when we take a look at view controllers.

In iOS applications, the UIApplication instance has a delegate object associated with it. Whenever you create an iOS project using one of the provided templates, Xcode will create an application delegate class for you. Take a look at the names of the source files in the project folder in the Project Navigator. The first file is named AppDelegate.swift.

The instance of this class is the delegate of the UIApplication singleton. Before taking a closer look at the AppDelegate class, we need to understand what the delegate pattern is.

Ole Begemann wrote an excellent article about the launch sequence of a typical iOS application. In his article, Ole talks about the various components involved and their role during the application launch sequence. I highly recommend reading this article if you want to get a better understanding of the role of the UIApplication class.

The Delegate Pattern

The delegate pattern is used extensively in Cocoa and Cocoa Touch. In a future article of this series, in which we explore the ins and outs of table views, you'll discover that table views rely heavily on the delegate (and data source) pattern.

Like the MVC pattern, delegation is common in object-oriented programming. The delegate pattern in Cocoa Touch, however, is slightly different, because it makes use of a delegate protocol to define the behavior of the delegate object.

Let's jump ahead and take a look at table views. If you've spent any amount of time with an iPhone or iPad, then the UITableView class should be familiar to you. It presents an ordered list of data to the user and it does this job very well.

How does a table view know what to do when a row is tapped? Is this behavior included in the UITableView class? Certainly not, because this behavior varies from application to application. If we were to include this behavior in the UITableView class, it would not be very reusable.

The table view outsources this responsibility to a delegate object. Put differently, it delegates this task to another object, a delegate object. Take a moment to inspect the class reference of the UITableView class. It has two properties named dataSource and delegate. The delegate is notified by the table view when the user taps a row. It is the responsibility of the delegate object to respond to that touch event.

The data source of the table view is similar. The main difference is that the table view asks the data source object for something, the data that it needs to display.

Delegate and data source objects, such as the table view's delegate and dataSource objects, are almost always custom classes. In most cases, it's up to the developer to create and implement these classes, because their implementation is specific to each application.

The Application Delegate

Now that we know what delegation is, it's time to explore the AppDelegate class Xcode created for us. At application launch, the application creates an instance of the AppDelegate class. This AppDelegate instance is then set as the delegate of the UIApplication instance the operating system created for your application. You never explicitly instantiate an application delegate object.

Open AppDelegate.swift to examine the implementation of the AppDelegate class. Ignoring the comments at the top, the first line imports the UIKit framework so we can work with its classes and protocols.

On the next line we see something we haven't covered yet, an attribute. Attributes in Swift start with an @ symbol and can be seen as instructions for the compiler. The @UIApplicationMain attribute tells the compiler that AppDelegate is the class that should be used as the application delegate. That is all you need to know about this attribute for now.

The next line should look familiar. This is the start of the declaration of the AppDelegate class. It specifies the name of the class and the class's parent class, UIResponder.

It also tells the compiler that AppDelegate conforms to the UIApplicationDelegate protocol. This isn't surprising since we already know that AppDelegate serves as the application's delegate.

The next line is a property declaration for the window property. Note that the property is a variable of type UIWindow?. The UIWindow class is a subclass of UIView, the base class for views on iOS.

The most interesting part of the interface of the AppDelegate class is the UIApplicationDelegate protocol. Take a look at the reference of the UIApplicationDelegate protocol for a complete list of the methods the protocol defines.

The protocol defines dozens of methods and I encourage you to explore a few of them to get an idea of the protocol's capabilities. The method that's most interesting to us at this point is application(_:didFinishLaunchingWithOptions:).

When the UIApplication object has finished preparing the application for launch, it notifies its delegate, the AppDelegate object, that the application is about to launch.

Why does it notify the application delegate of this event? The UIApplication instance notifies its delegate about this event so that it has an opportunity to prepare for application launch. The implementation of application(_:didFinishLaunchingWithOptions:) is pretty short as you can see below.

It provides a reference to the UIApplication instance and a dictionary of options. You can ignore the dictionary of options for the time being. To make sure the application is launched by the operating system, we return true.

Storyboard

The Xcode project contains another interesting file, Main.storyboard. The storyboard defines what the user interface of your application looks like. By default, the storyboard is named Main.storyboard. Select the storyboard to open it.

The Main Storyboard of the Project

The storyboard currently contains one view in the central workspace. On the right of the Project Navigator you can see a list of items, which are the objects you see in the view. The top item, View Controller Scene, contains one child item, View Controller.

The View Controller object also has a number of child items, but there is one that is of special interest to us, the object named View. Remember the discussion about the MVC pattern. You can now see the MVC pattern in action. The model is missing at the moment, but we do have a view, the View object, and a controller, the View Controller object.

When the application launches, the storyboard is used to create the application's user interface. The view controller is automatically instantiated and so is the view controller's view. The View object in the storyboard is managed by the view controller.

Wait a minute. Where can I find the class of the view controller in the storyboard? How can I change its behavior to create a unique application? Select the View Controller object on the left and open the Identity Inspector on the right.

The Class of the View Controller

The Identity Inspector tells you everything you need to know. At the top, in the section Custom Class, you can see the name of the view controller's class, ViewController. Have you noticed that the file we haven't talked about yet bears the same name? We'll explore this file in a few moments.

The view controller is instantiated for us, because it is the initial view controller of the storyboard. This is indicated in the storyboard by the arrow pointing to the View Controller Scene.

The arrow points to the initial view controller of the storyboard

UIViewController

If you open ViewController.swift, you'll notice that the ViewController class is a subclass of UIViewController. Like AppDelegate, the UIViewController class is a subclass of UIResponder. View controllers, or subclasses thereof, fall in the controller category of the MVC pattern. As the name implies, they control a view, an instance of the UIView class, which belongs to the view category of the MVC pattern.

As we'll see later, a view controller manages a view and its subviews. To do this, the view controller needs to know about the view. In other words, it needs to have a reference to the view.

The view controller in the storyboard has a reference to the view. You can verify this by selecting the view controller in the storyboard and opening the Connections Inspector on the right.

The view controller has a reference to its view

In the Connections Inspector, you should see a section named Outlets. The term outlet is a fancy word for a property that you can set in the storyboard. Hover with your mouse over the outlet named view and observe how the view in the workspace is highlighted. That is the connection between the view controller and the view.

UIView

Even though your application can only have one instance of UIWindow, it can have many views. The UIView class is an important component of the UIKit framework, because many classes inherit from it—directly or indirectly.

Revisit Main.storyboard by selecting it and take a look at the Object Library at the bottom of the Inspector.

Browsing the Object Library

Browse the Object Library and drag a label and a button to the view in the workspace. It doesn't matter where you position them in the view as long as they are in the view controller's view.

Adding a Label and a Button to the Storyboard

Notice that two new objects have been added to the Objects section on the left. Both the label (UILabel) and the button (UIButton) inherit from UIView. Have you noticed that the Label and Button objects are slightly indented compared to the View object? This indicates that the Label and Button objects are subviews of the View object. A view can have one or more subviews that it manages.

As I mentioned earlier, the UIView class is an important component of UIKit. A view manages a rectangular area or frame on the screen. It manages the contents of the area, the subviews, and any interactions with the view's contents. The UIView class is a subclass of UIResponder. You'll learn much more about views over the course of this series.

Outlets

Let's take a look at an example to illustrate the relationship between the storyboard, the view it contains, and the view controller. These three components are important and I want to make sure that you understand just how they work together.

A few moments ago, you added a label and a button to the view controller's view. How does the view controller know about these objects? At the moment, they don't appear in the Connections Inspector, but we can change that by telling the view controller about them. Open ViewController.swift and add a property for the label and one for the button.

By adding the @IBOutlet attribute to the property declaration, the properties appear in the Connections Inspector in the storyboard and that's what we want.

Head back to the storyboard, select the View Controller object in the View Controller Scene, and open the Connections Inspector on the right. The new properties are now listed in the list of Outlets. However, the view controller hasn't made the connection between the new properties and the objects in the storyboard yet.

This is easy to remedy. Drag from the empty circle on the left of the myLabel outlet to the label in the workspace. This will create the connection. The view controller now knows about the label. Repeat this step for the button.

Connecting Outlets in the Storyboard

Even though we can change the text of the label in the storyboard, let's do this in the view controller to illustrate that the view controller has access to the label and button in the storyboard.

Open ViewController.swift and look for theviewDidLoad() method. Modify the viewDidLoad() method to reflect the implementation below. Comments have been omitted for clarity.

We can send messages to the label property by accessing the view controller's myLabel property. We can change the text of the label by setting the label's text property, using a string literal.

The viewDidLoad() method is automatically invoked when the view controller has loaded its view. The override keyword indicates that we are overriding a method that is defined by a class higher up in the inheritance tree. The UIViewController class, the parent class of the ViewController class, implements this method.

Also note that we invoke viewDidLoad() on super. What is super? Just like self refers to the current instance, super refers to the parent class, UIViewController. In other words, we invoke the viewDidLoad() method on the superclass. This is often important when overriding a method in a subclass, because the superclass may be carrying out important tasks in its own implementation and we don't want to break anything.

Run your application in the simulator by clicking the Run button in the top left. Notice that the label's text has been updated. Don't worry about the position of the label and button. That's something we'll fix in the next tutorial.

Actions

We've explored a lot of new things in this article. I want to end this installment by talking about actions. Just like outlets, actions are nothing more than methods that you can access in the storyboard.

Let's see how this works. Open ViewController.swift and add the following method below the viewDidLoad() method.

Don't be confused by the @IBAction attribute. This attribute indicates that the method is an action and, therefore, accessible in the storyboard. If we take a closer look at the changeColor(_:) action, we can see that it takes one argument of type UIButton.

As the argument name implies, the argument of the method or action is the object that sent the message to the view controller. I will explain this in more detail in just a bit.

Revisit the storyboard, select the View Controller object in the View Controller Scene, and open the Connections Inspector. A new section has appeared in the Connections InspectorReceived Actions, and the action we just added is listed in this section.

Connecting the Action in the Storyboard

Drag from the empty circle on the left of the action to the button in the workspace. A pop up menu with a list of options should appear. The list contains all the possible events that the button can respond to. The one that interests us is Touch Up Inside. This event is triggered when a user touches the button and lifts her finger within the bounds of the button.

Choosing the Appropriate Touch Event

Run your application one more time and tap the button. The view controller's view should change color every time you tap the button. We added two print statements to the changeColor(_:) action. Let's see what the output looks like when you tap the button.

The first line displays the class of the sender, an instance of UIButton. This proves that it is the button that's triggering this method on the view controller. It's sending a message of changeColor(_:) to the view controller.

The second line displays the superclass of the sender. Remember that not every class has a superclass. That's the reason we get back an optional. The output tells us that the parent class of UIButton is UIControl.

The method itself is pretty simple. We generate three random integers between 0 and 255, pass these values to init(red:green:blue:alpha:) to generate a random color, and update the background color of the view controller's view with the randomly generated color. Note that view references the view that the view controller manages.

Conclusion

In this article, we explored a few classes of the UIKit framework and we took a close look at the various components of an iOS application. We'll explore and work with the UIKit framework in more detail in the rest of this series. If you don't fully understand the various concepts and patterns, then I'm sure that you will as the series progresses.

If you have any questions or comments, you can leave them in the comments below or reach out to me on Twitter.

Tags:

Comments

Related Articles