This is a three-part guest tutorial post by Johnson Ejezie, an Andela developer based in Lagos.
iOS app: From scratch to app store Part 1
What we will be building
We will be using the traktv api to build a movie and tv show app. We will be figuring out functionalities to add to our app as the tutorial progress. We will encounter various concepts of iOS development and swift language while building the app and we will discuss these concepts.
What you will need for this tutorial
- iPhone (simulator can be used for testing but when we get to submitting our app to app store, this becomes necessary)
- I’m excited. I hope you are. Let’s begin.
iOS app: From scratch to app store Part 2
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.
Like I said in the first part of this tutorial, we will be building an app that, among other functionalities, will be displaying a 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
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.
- 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.
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.
In the popup, select Move to Trash.
Right click on the folder tvzone and select New File Under iOS, Source, select Cocoa Touch Class and click next.
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)
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.
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:
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:
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.
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.
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.
2. 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
- 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.
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:
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.
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.
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:
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”.
We are done. Lets go ahead and test it. Go to the Toolbar area on Xcode.
Select the simulator you want to run the app on. Mine is iPhone 6.
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.
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.
Check the box next to it and run the app again. This time, it should work just fine.
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
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.
For each corner in the pin, set to zero and click on the faint red red line on each corner to activate the constraints.
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.
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.
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”.
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.
ListViewController should look like this:
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.
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.
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:
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.
Go ahead and run the app now.
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.
AppDelegate: 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.
launch Screen: The screen that appears instantly when your app starts up.
iOS app: From scratch to app store Part 3
Here is the link to the project we worked on in part two. We will build on this. The project was initially written in Swift 2.2 but I have updated it to swift 3. In part 2 we agreed will be building a custom cell to display each movie/tv shows. Here is a screen shot of what we want to achieve.
At the top we have a label for the name of the movie/tv show. Right below the name is an image. Next is a label for the release date and finally a summary/synopsis. Also the cells is designed as cards with the edges curved a bit.
Lets get right into it.
Right click on tvzone folder, select New File > Cocoa Touch Class. Click on Next. For “Subclass of:” select UITableViewCell. Check Also create XIB file. Name the class MoviesTableViewCell. Click next, click Create.
Click on MoviesTableViewCell.xib. This is where we will design the custom cell and support it with little code.
Select the cell, click on size inspector. For Row Height check custom, and give it a height of 350. Below RowHeight you will find Width and Height properties of the cell. Set width to 320 and height to 340. We will let the content of the cell determine the size of the cell but for now 350 gives us a size to work with in the interface. The editor area should look like this now
Drag a view from the Object library onto the cell’s Content View. With the view selected, click on Pin and pin the view to all corners of the content view. top:5, bottom:5, leading:8, trailing:8.
Let’s call this view, “Card View”. To do this, click on identity inspector, just right below “Document” you will “Label”, enter “Card View” for the field.
Create an IBOutlet for the view. You do this by opening the assistant inspector and click > dragging (while holding control button) from card view to it’s class. Call the outlet cardView.
Notice the “Spring Wood” color of the background of the card in the screenshot. Lets apply the same color to our card view. We will do this in a UIView method called layoutSubviews. According to apple:
Subclasses can override this method as needed to perform more precise layout of their subviews. You should override this method only if the autoresizing and constraint-based behaviors of the subviews do not offer the behavior you want. You can use your implementation to set the frame rectangles of your subviews directly.
Though layoutSubviews sounds likes where we can only alter the layout/frame of our subviews, we can also take advantage of it to alter some other components of the subviews that doesn’t relate to the views frame.
- The first line of code sets the background color of the card. To set color in iOS, we use the UIColor object which has an init method this takes opacity and RGB component values to create and return a color object
- There is a tiny faint-colored border line around the card. We give the card a borderWith of 1 and set the color of the border to lightGray. We get the color using the UIColor object, adjust the opacity to 0.3.
- The edges of the card is not sharp, it’s a little curved. To achieve this, we set the cornerRadius property of the layer. We set this to a fraction of the card width. We add some little effect by setting the shadowRadius, shadowOpacity and shadowOffset.
Now let get back to cell interface. Grab a label and place inside card view. Pin it 8 to the left and right and 4 to the top. With the label selected, go over the Utility Area, select Attributes inspector. Let’s change the font. Click on the bold “T” to the extreme end of font field.
For font, click on the drop down and select Custom, for family select Avenir, for style, select Medium. Give it a size of 20.
Right underneath Font is Alignment. Select the second option to center the text in the label.
Go to the Object Library, get an ImageView and drop it vertically right next to the label. Pin the image view 8 to both left and right. 4 to the top
Next we add two more label. One for year of release and one for summary.
Year of release label: Pin 4 to the image view, 8 both left and right of card view. Change font to Avenir, style: Book, size: 15.
Summary label: Apply same font for year of release. Pin 4 to Year of release label, 8 left and right. Pin to the bottom too.
With the summary label selected, go over to Size Inspector. scroll down to the constraints. Lets edit the bottom constraint. Click on edit on the “Bottom Space to:SuperView”.
Change Constant to >=, and the value to 8.
This will allow card view to make space enough for the summary label content.
With the label still selected, go back to attribute inspector. Right below Alignment is Lines. UILabel has a property called “numberOfLines” which specifies the maximum number of lines to use for rendering text. We will set this to 0 since we don’t know the actual number of lines we will need for the summary text.
At this point, our cell should look like this
Lets go ahead and wire the elements to the class.
Click on Assistant editor. Make sure the MoviesTableViewCell file is the one displayed in the assistant editor. While holding down control on keyboard, click and drag from the first label to MoviesTableViewCell class. Call the outlet titleLabel. Do the same for the imageView (movieImageView), year of release label (releaseDateLabel) and summary label (summaryLabel).
Finally we can concentrate on code now. Go over to ListViewController. Our table will be displaying a list of movies so we can go ahead and delete the “names” array. We create an array called movies. This will be an array of dictionaries. Our table will display a list of two movies. Since we already have a picture of Messi and Ronaldo, let create a movie for the two stars.
For summary I just grabbed something from the Wikipedia.
The table view has no knowledge of the existence of our custom cell, we have to register the cell. We will do this in viewDidLoad. But first, go to main storyboard and create an outlet for tableView. Call it tableView.
So the tableView can be a able to dequeue the custom cell, we register a nib object containing the custom cell with the specified identifier.
Go to MoviesTableViewCell.xib and give the cell a reuse identifier MoviesTableViewCell
You must noticed an error from the moment we deleted the array names. Let fix that. For numberOfRows return
We change the implementation of cellForRowAt indexPath
We create the cell and forcefully cast it to type MoviesTableViewCell. This is fine since we are sure it is of that type. The movies array is an array of dictionaries. We can grab each dictionary/movie using indexPath.row each time cellForRowAt indexPath is called. This we did with the line of code
We then set the cell contents by accessing the values of the dictionary using the keys. Finally we returned the cell.
Run the project now.
That is not what we want to achieve.
We forgot to set the size for our cell. To do this, we will implement two method from UITableViewDelegate.
The first method asks the delegate for the estimated height of a row in a specified location. While the second asks the delegate for the height to use for a row in a specified location.
If we have a fixed size for our cell, we could return that size. Say we want our cell to be height 250, then we return 250. In this case we don’t have a fixed size. We want the cell to take the size of it’s content. UITableViewAutomaticDimension requests that UITableView use the default value for a given dimension.
Before we run the project, go main storyboard, and set the delegate for the table view. Same way we set the datasource in part one.
Run the project.
The complete project can be found here.
In part 4 we will be adding traktv api and see how to pull content from a web service.