Menu

iOS app: From scratch to app store Part 2

27 August 2016

TableViews
The UIKit (User Interface Kit) is the framework that defines the elements of the graphic interface for mobile application. Basically all components such as buttons, labels, views, switches etc are defined by the classes in UIKit.
Table views are among the most used components of the UIKit framework. Table Views present the user with data in a list format.
<img src="/content/images/2016/08/nameList.png" alt="Alt Text" text-align:"center" style="width:160px;height:300px;">
Like I said in the first part of this tutorial, we will be building an app that, amongst other functionalities, will be displaying list of movies and tv shows. We will need a Table View to display this list. So lets see how we can create a Table View.

First we create our app. Open Xcode and click on Create a new Xcode project
<img src="/content/images/2016/08/createNewProject.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">
By default, Application under iOS is the selected option in the list of options on the left pane. On the right pane, Xcode presented five options.
<img src="/content/images/2016/08/chooseTemplate.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">

Master-Detail Application: This template provides a starting point for a master-detail application, using a split view controller to display a list of items and a detail view.

Page-Based Application: This template provides a starting point for a page-based application that uses a page view controller.

Single View Application: This template provides a starting point for an application that uses a single view. It provides a view controller to manage the view, and a storyboard or nib file that contains the view.

Tabbed Application: This template provides a starting point for an application that uses a tab bar. It provides a user interface configured with a tab bar controller, and view controllers for the tab bar items.

Game: This template provides a starting point for games.

We won’t go into details; at least not now.

Select Single View Application and click next.
Enter the product name. We will call our app, tvzone. Enter your organization name. Enter the Organization Identifier which will be used to identify your app. All bundle IDs need to be unique. The org identifier is a way of making sure your apps (iOS, tvOS, MacOS) are separate from any other organization's apps. It provides a prefix to the bundle ID.

Select swift as language and for devices select iPhone. Make sure Use Core Data is unchecked. We will add persistence later. Also ensure Include Unit Tests and Include UI Tests are both unchecked. We will have a separate tutorial for testing.
<img src="/content/images/2016/08/newProject.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">
Click next. Select the folder you want to keep the app, click create.

I know Xcode looks intimidating if it is your first time. We will explain every part of it as we progress.

Go over to the navigator area. We want to delete the file ViewController.swift. Right click on it and select Delete.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-9-13-58-AM.png" alt="Alt Text" text-align:"center" style="width:300px;height:300px;">
In the popup, select Move to Trash.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-7-08-04-AM.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">

For Subclass of, select UITableViewController and name the class “TableViewController”(This is not a very good name for a class. I know. This is for testing)
<img src="/content/images/2016/08/TableViewControllerSubclass.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">

TableViewController: The UITableViewController class creates a controller object that manages a table view.

Click on the class we just created. Notice the boiler plate codes in Xcode Editor Area that come with UITableViewController; most if which are commented out. Delete all except the method viewDidLoad. We don’t necessary need it for now but I want to talk about it now.

ViewDidload: This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.

Functions in Swift: A function is a set of statements organized together to perform a specific task. The syntax of function in swift is as shown below:

func: keyword used to notify swift compiler that this is a function.funcName: name assigned to the function.parameterName: parameter passed to the function.parameterType: data type of the parameter.returnType: the data type of the result that the function will return.

Time to write some code!
The first thing we want to do is declare an array containing the data we want to display in our table.

The first thing you must have noticed is the let keyword. This key word defines a constant. The names variable we declared can not be changed afterwards because its a constant. The var keyword is used to define a variable that can be changed.

var age = 45
age = 21

Age is now 21. Xcode will throw error if we write the above code using let.names, is the name of the variable we declared and it contains a list of names. This datatype is called an Array.Arrays: Arrays are variables that contain an orderlies of values. The values stored in an array must be of the same type. Our array contains only values of type String.
This is not allowed:var list = [“Dog”, “House”, 42]
This is not allowed because 42 is of type int and not String.

An index is assigned to every element in an array starting from 0. To access a value/element in an array, we use the index of that element. If we print:

print(names[4)]

we get Vilma Hammell. Remember the first element in the array is given an index of 0, the second index 1…
If you like to know more about array right now, go here.

Next we have write code that will display the content of the array “names” on a tableView. To do this, we have first talk about dataSource and delegate.

Data Source
The data source provides the table-view object with the information it needs to construct and modify a table view. The dataSource implements the UITableViewDataSource protocol, which basically consists of a number of methods that define title information, how many rows of data are to be displayed, how the data is divided into different sections and, most importantly, supplies the table view with the cell objects to be displayed.

Delegate
The delegate implements the UITableViewDelegate protocol and provides additional control over the appearance and functionality of the table view including detecting when a user touches a specific row, defining custom row heights and indentations and also implementation of row deletion and editing functions.

We only have to implement the datasource method for now.
Just after viewDidLoad, write this

These preprocessor features allow to bring some structure to the function drop down box of the source code editor. It is used to mark a section of code, making it easier to navigate to different sections.
<img src="/content/images/2016/08/mark.png" alt="Alt Text" text-align:"center" style="width:500px;height:100px;">

numberOfSectionsInTableView method is called by the table view to get the number of sections to create. We only want one section, so we return 1

numberOfRowsInSection tells the table view the number of cells to create for each section. We only have one section and in this section, we want to display the names in the array “names”. We have 13 names in the array. But we don’t have to hardcode this. Array has a property count, that gives us the size of the array. So we return names.count

cellForRowAtIndexPath: Each time the table view controller needs a new cell to display it will call this method and pass through an index value indicating the row for which a cell object is required.

Here we are trying to create a cell or reuse cell that has been scrolled out of view. Cell which is of type UITableViewCell, are views and views occupy memory. Imagine we have 1000 names to display. Creating 1000 cells will be quite expensive in terms of memory. To solve this, UITableView only creates number of cells that can be visible on device at once. When we scroll, the cell that are scrolled out are not discarded. They are reused.
What are UITableViewCell? According to Apple :

The UITableViewCell class defines the attributes and behavior of the cells that appear in UITableView objects. This class includes properties and methods for setting and managing cell content and background (including text, images, and custom views), managing the cell selection and highlight state, managing accessory views, and initiating the editing of the cell contents.

A cell has a textLabel property. An element in an array can be accessed through the index. indexPath has a property row, an integer, which we can use as index to get into the names array. We grab a name from names and set the cell textLabel text.

we return cell.

We are almost done. The controller is done, we only need to do some setting on the view. Click on Main.storyboard.Storyboard is where we will design user interface. When we created the project, Xcode generated a viewController.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-5-39-34-AM.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">
Select the viewController by clicking on empty space at the top where 3 icons reside. Hit backspace/delete.
We need a Table View Controller, not a viewController. Go to object library and start typing “table” in the filter:
<img src="/content/images/2016/08/object-library.png" alt="Alt Text" text-align:"center" style="width:300px;height:300px;">
Drag a Table View Controller to the editor area.
First thing we want to do is assign a class to our Table View Controller. So click on the yellow icon at the top of the Table View Controller we just dragged in. Go to the Utility Area.
<img src="/content/images/2016/08/TableViewClass.png" alt="Alt Text" text-align:"center" style="width:160px;height:290px;">
Click on identity inspector; the third icon from left at the very top. For the field class, type in the name of the Table View Controller we worked on.

Select the table view cell; the white rectangle with Prototype Cells written on it.
<img src="/content/images/2016/08/prototypecell.png" alt="Alt Text" text-align:"center" style="width:400px;height:100px;">
Remember in our Table View Datasource, the cellForRowAtIndexPath will want to reuse a cell we identified as “Cell”. To enable the controller find this cell, we have to give the cell a reuse identifier.
To create or reuse cell we did:let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)

Pay attention to dequeueReusableCellWithIdentifier, where we passed “Cell” as the identifier.
With Prototype cells selected, go to the Utility Area and click on Attribute inspector(third icon from right)
For the field identifier, type “Cell”.
<img src="/content/images/2016/08/reuseIdentifier.png" alt="Alt Text" text-align:"center" style="width:180px;height:210px;">

We are done. Lets go ahead and test it. Go to the Toolbar area on Xcode.
<img src="/content/images/2016/08/Toolbar.png" alt="Alt Text" text-align:"center" style="width:400px;height:15px;">
Select the simulator you want to run the app on. Mine is iPhone 6.
<img src="/content/images/2016/08/changeSimulator.png" alt="Alt Text" text-align:"center" style="width:400px;height:300px;">
Hit the play button on the toolbar area or press command + R on keyboard. Wait for Xcode to Build and Run the app.
If you ended with a black screen as I did, it is because we did not set the initial View Controller. Check the debug area, Xcode has a message for us.
<img src="/content/images/2016/08/debug.png" alt="Alt Text" text-align:"center" style="width:420px;height:90px;">
Main.storyboard can take more than one storyboard. The only way to know which View Controller to show first, is to set in on the interface or via code. In other words, we have to set the entry point of our app.
Go to the storyboard. Select the table view. With Attribute inspector selected in the Utility area, you will find Is initial View Controller right under View Controller section.
<img src="/content/images/2016/08/assignClassToView-1.png" alt="Alt Text" text-align:"center" style="width:200px;height:300px;">
Check the box next to it and run the app again. This time, it should work just fine.
<img src="/content/images/2016/08/istNames.png" alt="Alt Text" text-align:"center" style="width:200px;height:400px;">
Easy right?

There is another way to create a table view using View Controller and not Table View Controller. Lets quickly go over it.
Delete the Table View in the storyboard. Go to Object Library and drag a View Controller into the editor. Look for Table View in the object library.
Note: Table View, not Table View Controller.
Drag the Table View and place it on the View Controller. You should have something like this
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-11-24-20-AM.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">
With the table selected, click on Pin icon on the bottom right of the editor area. Pin is the second from right.

We want to pin the table view to the top, left, right and bottom corners of the View Controller.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-6-47-52-AM.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">

For each corner in the pin, set to zero and click on the faint red red line on each corner to activate the constraints.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-6-48-03-AM.png" alt="Alt Text" text-align:"center" style="width:200px;height:250px;">
Uncheck Constrain to margin. Go to Update Frames, select Items of New Constraints.
Click on Add 4 Constraints. Your View Controller should look like this.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-6-53-38-AM.png" alt="Alt Text" text-align:"center" style="width:300px;height:300px;">
It’s ok if you don’t understand what we just did now. We will discuss auto layout in part 3 of this tutorial.
Next we want to set the data source and delegate for the Table View. Holding the Ctrl button on your keyboard, click drag from the table view to the yellow icon on the View Controller and release.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-11-29-55-AM.png" alt="Alt Text" text-align:"center" style="width:300px;height:300px;">
Select datasource from the popup. Repeat and select delegate. Our view controller is now wired up to act as the data source and the delegate of the Table View.
Note: We didn’t have to do this for Table View Controller because this is already set in it.

Now we have to create a View Controller class for the interface we just created. Delete the Table View Controller class. Right click on tvzone folder and select New File. The class should be a subclass of UIViewController. Call it “ListViewController”.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-7-11-39-AM.png" alt="Alt Text" text-align:"center" style="width:420px;height:300px;">

Delete very code in the class, including viewDidLoad. Create an array of names. Similar to what we did in Table View Controller class.
To be able to act as data source, our ListViewController must extend UITableViewDataSource and conform to it's protocol.
Outside the View Controller class, we extend the ListViewController and implement the UITableViewDataSource protocol.

The only new term here is extension. Extensions let you extend and add new functionality to an existing type, class, structure or enumeration. You can extend existing types, both your own and those from external libraries or those from Swift itself.

Get back to storyboard. You should be able to do the following yourself:

Set the ListViewController as the class of View Controller

Drag a Table View Cell from the Object Library to the Table View on our View Controller

Select the cell and set the reuse identifier as “Cell”.

Set our View Controller as the initial View Controller

Run the app now. Easy!!

Let’s quickly add an image. Get two image of your choice. I will be using photo of messi and ronaldo. Don’t ask me who is a better player between the two.
<img src="/content/images/2016/08/messi-1.jpg" alt="Alt Text" text-align:"center" style="width:300px;height:200px;">
<img src="/content/images/2016/08/ronaldo.jpg" alt="Alt Text" text-align:"center" style="width:300px;height:200px;">Adding Image to Xcode
Click on Assets.xcassets in navigator area. drag the images from finder to the editor area of Assets.xcassets. Note the name of the images.
<img src="/content/images/2016/08/Screen-Shot-2016-08-27-at-7-57-29-AM.png" alt="Alt Text" text-align:"center" style="width:500px;height:300px;">
Go to ListViewController class. cellForRowAtIndexPath is where we configure our cell. We don’t have different images for each cell, so we’ll be alternating between the two images we have.

Aside having a textLabel property, UITableViewCell has imageView property. The imageView is of type UIImageView.
A UIImageView object displays a single image or a sequence of animated images in your interface. Image views let you efficiently draw any image that can be specified using a UIImage object.
A UIImage object manages image data in your app. You use image objects to represent image data of all kinds, and the UIImage class is capable of managing data for all image formats supported by the underlying platform.

In cellForRowAtIndexPath method, add the following code just before returning the cell.

If statement is a conditional statement we use to check a condition and execute a group of instruction if the condition is true. When used together with else, then we can execute a different group of instructions if the condition is false. The syntax for if..else statement is show below:

if boolean expression {
execute the code here if expression is true
}else {
execute the code here if expression is false
}

Since we want to alternate between Messi and Ronaldo images, we check if the integer indexPath.row is an even number. If it is, use Messi’s image. If it is not, use Ronaldo’s image.
The symbol % is call modulus operator and it simply return the remainder of after an integer/float division.
If the remainder is zero, then indexPath.row is even.UIImage(named: "messi") is simply initializing/creating a UIImage using the image asset name “messi”
We then assign this image to the image property of the cell’s imageView.

It’s not that pretty, that’s ok for now. In part 3 we see how to build a custom UITableViewCell for our movies/tv shows app. Something like this.
<img src="/content/images/2016/08/IMG_3366-1.PNG" alt="Alt Text" text-align:"center" style="width:200px;height:300px;">

MiscellaneousAppDelegate: According apple doc,

The app delegate works alongside the app object to ensure your app interacts properly with the system and with other apps. Specifically, the methods of the app delegate give you a chance to respond to important changes. For example, you use the methods of the app delegate to respond to state transitions, such as when your app moves from foreground to background execution, and to respond to incoming notifications. In many cases, the methods of the app delegate are the only way to receive these important notifications.

info.plist: An information property list file is a structured text file that contains essential configuration information for a bundled executable.