Learn iOS 12 Programming
Learn iOS 12 Programming
1 Introduction to Xcode 10
3 Shopping List
Xcode is the IDE that we use to build apps for iOS devices and MacOS. There are four
main areas in Xcode. On the left side is the Navigator area.
1
In the navigator area we can use the navigator bar to get to the different parts of the pro-
ject.
1 - Project navigator
3 - Symbol navigator
4 - Find navigator
5 - Issue navigator
6 - Test navigator
7 - Debug navigator
8 - Breakpoint navigator
9 - Report navigator
2
In the middle is the Editor area.
This is the main window where you can edit your source code. You can switch between
the Standard editor, the Assistant editor and Version editor with the buttons on top right.
3
On the right side is the Inspector area.
4
The inspector bar lets you switch between the following inspectors from left to right.
1 - File inspector
3 - Identity inspector
4 - Attributes inspector
5 - Size inspector
6 - Connections inspector
5
At the bottom we have the debug area.
You can hide or show all of these areas with the button on the top right corner of Xcode.
6
When you have the storyboard open you can open the object or media library with this but-
ton next to the standard editor button.
If you are editing a source code file, the button changes and you can open the snippets li-
brary.
You can use the play button to build and run your apps in the simulator or on your device.
You can change the device your app runs on from the dropdown menu.
7
2
Body Mass Index Calculator
In this chapter we will build a body mass index calculator app. The user will enter a per-
son’s height and weight and the app will calculate their body mass index. The app will
have two text fields to enter data, a button to calculate the result, and a label to show the
calculated result. The app will look like the following when we are finished.
8
Open Xcode and create a new project.
9
Select “Single View App” template under iOS project and click Next.
10
Type “Body Mass Index Calculator” for product name. Organization name and identifier
could be anything you want for this tutorial. Keep the language Swift.
Click next, choose a place to save your project and click create.
11
Once you have created your project open Main.storyboard from the project navigator then
open the object library.
Find and drag two text fields to the view controller scene. One will be for the height and
the second one will be for the weight.
12
Both height and weight will be numbers not characters so we need to change the key-
board type for each text field that will be used to enter values. Select the first text field, go
to the Attributes Inspector (top right in Xcode) and change Keyboard Type to Number Pad.
Do the same for the second text field.
13
We also need to drag two labels from the object library. Change the text of the labels by
double clicking on them and typing “Height in inches” and “Weight in pounds”
14
We would need a button to calculate the BMI value. Again, from the object library, drag a
button and change its title to “Calculate” by double clicking on it and typing the new title.
15
Lastly we need a label to show the BMI value. Drag a label from the object library and put
it below the calculate button. Change the text of the label by double clicking on it to
“BMI:”
16
To be able to access the text in the text fields in need to set outlets.
Open the Assistant Editor by clicking on the icon with two circles in Xcode.
You can also open the the Assistant Editor by going to View->Assistant Editor->Show As-
sistant Editor.
On the left side you will have Main.storyboard open and on the right side the
ViewController.swift file.
To set outlets press control on the keyboard then left click with the mouse and drag from
the height text field to the ViewController.swift just below the class ViewController defini-
tion.
17
Once you let go of the mouse a pop up window will appear. Set the name to heightText-
Field and click Connect.
Do the same and create an outlet for the weight text field with the name weightTextField.
We need to create an outlet for the result label, because we would want to present the re-
sult of the bmi when its calculated. Control and drag again from the “BMI:” label to
ViewController.swift and name the outlet resultLabel.
Three IBOutlets should be added to the ViewController.swift file when you are done with
setting up the outlets.
18
An action needs to be set up for the Calculate button. This is done similar to setting up an
outlet. Press control and drag from the Calculate button to the ViewController.swift file just
below the viewDidLoad( ) method. The same pop up window will come up. To set an ac-
tion just change the connection type to Action. Set the name to calculateBMI and click
connect.
This is the action method created in ViewController.swift and every time the Calculate but-
ton is tapped this method will be called.
19
Let’s change the background of the view so its easier to see the text fields. Open
Main.storyboard then open the Document Outline if its not already open. Select the View
under the View Controller.
20
With the view selected go to the attributes inspector and change the background color to
gray or any other color you want.
21
To make everything centered on the screen we are going to put all elements in a stack
view and then set constraints. First, set the text fields width constraints by selecting the
height text field and then clicking on the Add New Constraints (lower right) button in
Xcode. When the pop up appears, check the Width checkbox. Change the value to 60
and click the Add 1 Constraint button. Do the same for the weight text field.
22
Next select both the height text field and the heigh label (hold shift and click on both of
them) and click the embed in button at the bottom of Xcode. Select the Stack View from
the pop up that appears.
In the document outline select the new stack view that was created and go to the attrib-
utes inspector and set its spacing to 8.
23
Do the same for the weight text field and weight label. Embed them in a horizontal stack
and then set the spacing to 8.
Once that is done. Select everything, the two stack views that you just created, the calcu-
late button and the result label and embed everything in a new stack view by clicking on
the embed in button again. Go to the Attributes Inspector again and increase the spacing
between the elements.
24
In the Document Outline you can see the stack view created and what is included in it.
The red arrow at the top right of the Document Outline tells us that we are missing con-
straints. To get rid of this error we have to set constraints to tell the app how we want the
stack view to be positioned.
In the Document Outline control + drag from the last created Stack View to the View.
25
When you let go, a pop up appears. Hold down shift and select “Top Space to Safe Area”
and “Center Horizontally in Safe Area” then click anywhere outside the pop up.
The red arrow on the top right of the Document Outline disappears after you add the con-
straints.
Select the Stack View again and double click on the constraint to the top and change the
value to 16.
We have the UI set up the way we want it. All that is left to do is to read the data the user
inputs, do the calculations, and show the results.
26
On line 21 and 22 we get the value from the text fields and cast them from String into Int.
On line 24 we use optional binding to make sure that height and weight are not nil. On line
25 we calculate the BMI. The formula to calculate body mass index is
703 * (weight /height 2). On line 26 we just format the results to show 2 decimal places and
we set the result label with the calculated value. The pow function returns a decimal so
we need to cast the result as a NSNumber and then get the double value. On line 28 we
dismiss the keyboard from the screen.
At this point you can run the app by going to the Xcode menu Product->Run or ⌘R or the
play button in Xcode and test it.
As an exercise put another label that shows if the BMI is the normal range (18.5 -
25) or in overweight range > 25.
You can download the source code for this app from http://bit.ly/2Pvh4N0
27
3
Shopping List
We are going to build a shopping list app that will allow us to add, delete, check and un-
check items. This is what the final app would look like when we are done.
28
In this chapter we are going to learn how to work with table views, protocols and data
sources. We are also going to learn about segues and how to present different view con-
trollers.
Create a new project using the Single View App template in Xcode (If you are not sure how
to do this, go over chapter 2 to review ). Name your app “Shopping List" We are not going
to use the view controller that was already created for us so we need to delete it. Select
ViewController.swift in the project navigator and press delete on the keyboard.
Open Main.storyboard and select the View Controller Scene in the document outline and
press delete, as well.
29
We are going to use a table view to display our shopping list. While you still have the story-
board open, open the object library.
Find a “Table View Controller” in the object library and drag it into the storyboard.
30
We need a backing class for this table view controller. Create a new file from the menu
File -> New -> File or ⌘N. Under iOS select the Cocoa Touch Class template. Name the
new class ShoppingListTableViewController and make it a subclass of UITableViewControl-
ler.
Go back to Main.storyboard and select the table view controller that was just created.
Open the identity inspector (top right). Change the custom class value to “ShoppingListTa-
bleViewController”. This class will be used as a datasource and delegate by the table view.
31
You will see that the name of the “Table View Controller” changes to “Shopping List Table
View Controller” in the storyboard.
While still having “Shopping List Table View Controller” selected in Main.storyboard, go to
the attributes inspector (top right) and check the “is Initial View Controller” checkbox. An
arrow should appear and point to the view controller. This tells Xcode where the app
should start when it launches.
32
To improve performance instead of creating a new cell for each row, the table view reuses
cells that are off screen to show content that is on screen. To be able to do that we need
to set the table view cell identifier. Select the Table View Cell in the document outline and
go to the attributes inspector. Put “Shopping List Cell” in the identifier field. Also, change
the accessory value to Checkmark. We want to check items that we have bought.
33
Each row of the table view will represent one shopping list item. Lets create a new class
for this object. Go to the menu File->New->File or ⌘N. Select the Swift File template un-
der iOS and click next. Name the file ShoppingListItem and click create.
34
Open ShoppingListItem.swift and create a new class ShoppingListItem with two proper-
ties. First one would be name which would be of type String and the second one would
be checked which would be of type Bool. Also create an initializer method. This is what
ShoppingListItem.swift should look like when you are done.
Lets create a few shopping list items so we can display them in the table view. Open
ShoppingListTableViewController.swift and declare a new property shoppingList which
would be an array that holds shopping list items.
The way that a table view represents data in iOS is for the table to ask its data source (in
our case ShoppingListTableView.swift is the data source) for the data. It calls three meth-
ods. The first is numberOfSections(in tableView: UITableView) it tells the table how many
sections it needs to display. The second is tableView(_ tableView: UITableView, numberO-
fRowsInSection section: Int) which returns an integer and tells the table view how many
rows it should display. The third method is tableView(_ tableView: UITableView, cellForRo-
wAt indexPath: IndexPath) which returns a UITableViewCell for each row that its being dis-
played.
35
Open ShoppingListTableViewController.swift and lets implement these methods. They
should be included in the template for the table view controller that we used to create
ShoppingListTableViewController.swift Just remove the /* and */ from the beginning and
end of each method. If they are not included add them yourself.
Our table will have only one section so in the first method numberOfSections we have to
change the return value from 0 to 1. When we have only one section in the table we can
also delete this method because if that method is not present, the default behavior of the
table view is to present only one section. So either delete the method or change the re-
turn value to 1.
In the second method we have to return the number of rows the table view needs to dis-
play. That would be the size of the shoppingList array, so change the return statement to
shoppingList.count. The method should look like this.
36
In the third method tableView(cellForRowAt:) we have to change the reuse identifier for the
cell to “Shopping List Cell”. We set this up at the beginning of the chapter in the attributes
inspector for the cell. The dequeueReusableCell gives us a cell that we can reuse if there
are any available or it creates a new one. After that we have to configure the cell and re-
turn it to the table view.
indexPath.row tells us what row the table view is trying to present and we use that value to
get the item that is at that index of the shopping list items array. Once we have the shop-
ping list item we get the name of that item and set it as the text label of the cell. If the
shopping list items has been checked already we set the accessory type of the cell to
.checkmark otherwise we set it to .none At this point none of the items have been
checked. Change the method to look like the following.
Build and run the app, and you should see the following.
37
We want the checkmark to appear when the user taps on an item. The delegate method
that handles a row being tapped is tableView(_ tableView: UITableView, didSelectRowAt in-
dexPath: IndexPath)
38
Run the app in the simulator ⌘R and tap on a shopping list item to see the checkmark ap-
pear next to it.
39
Let’s say we want to delete items from the shopping list. We need to implement the dele-
gate method tableView(_ tableView: UITableView, commit editingStyle:
UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath). Add the following to
ShoppingListTableViewController.swift
First we remove the item from the shopping list model and then we delete it from the table
view. We can also reload the whole table view after we remove the item from the shopping
list model instead of using deleteRows.
Run the app ⌘R and left swipe on a shopping list item. A red button “Delete” appears.
When you tap the delete button, the row is removed from the shopping list.
40
We also have to be able to add new items to the list. We need to add a new view control-
ler where we will have a text field and a button. We will use a segue to present this new
view controller on screen. First we have to embed the table view controller in a navigation
controller. Open Main.storyboard, select the Shopping List Table View Controller and go
to the menu Editor->Embed In->Navigation Controller
41
Open the object library and drag a bar button item to the navigation bar of the Shopping
List Table View Controller. We will use this button to add new shopping list items.
42
Select the newly created bar button item and go to the attributes inspector. Change the
value of System item to “Add”. You will see the bar button changes to a + sign.
43
When we tap the + button we want to show a new screen where we can add more items
we want. Find a View Controller in the object library and drag it to the storyboard. Put it
next to the shopping list table view controller.
44
We would also need a backing class for this view controller. Create a new file ⌘N Select
Cocoa Touch Class template under iOS, name it AddItemViewController and make a sub-
class of UIViewController. Go back to the storyboard and select the new view controller
that we just created. Go to the identity inspector and change the custom class to Ad-
dItemViewController.
Lets set up the text field and button for the Add Item View controller. From the object li-
brary drag a text field and a button to the Add Item View Controller scene. Change the ti-
tle of the button to “Add Item”. Select the text field and click the add new constraints but-
ton (lower right.) Click on the red bars for left top and right constraints to select them and
then put 16 in all three text fields for the constraints. Click “Add 3 Constraints” button
when done.
45
Add the constraints for the button “Add Item” the same way you did it for the text field.
This is what the view controller should look like when you are done.
46
To get to the Add Item View Controller we will use segues. In the Shopping List Table View
Controller press control and drag from the + button to Add Item View Controller. When the
pop up menu appears select the Show segue.
47
Select the segue, go to the Attributes inspector and set the segue identifier to “AddItemSe-
gue”
Run the app ⌘R and when you tap on the + button the Add Item View comes on screen.
Right now the Add Item button is not doing anything. We have to set up an action for the
button and an outlet for the text field so we can read the text that the user types in. We
will use protocols to send the data from the Add Item View Controller to the Shopping List
Table View Controller.
Lets write the protocols first. Open AddItemViewController.swift and add the following just
bellow the import UIKit line.
48
We define a protocol AddItemViewControllerDelegate that defines one method addShop-
pingListItem which we call with the new item to be added to the list.
All we are doing in this method is adding the ShoppingListItem to the shoppingList array,
reloading the table view, and removing the AddItemViewController from screen.
49
When we segue from the Shopping List Table View Controller to Add Item View Controller
we have to set the delegate property in the prepare(for segue: UIStoryboardSegue,
sender: Any?) method. Implement the following method in
ShoppingLIstTableViewController.swift
Prepare for segue is called when we tap the + button. We check to make sure we are
working with the AddItemSegue. We read the segue destination value, cast it to a Ad-
dItemViewController, and set the delegate for the AddItemViewController as self (Shop-
pingLIstTableViewController)
All that is left to do is to set the outlets and action in Add Item View Controller. Go to the
storyboard and select the Add Item View Controller. Press the assistant editor button.
It should open AddItemViewController.swift file on the right side of the window. Create an
outlet for the text field and name it “textFieldOutlet”. Create an action for the Add Item but-
ton and name it “addItemTapped” (If you don’t know how to create outlets or actions go
over chapter 2 to review.) Change addItemTapped action method to look like the follow-
ing.
Line 27: we unwrap the optional text field value and check that its not empty.
50
Line 28: we create a new shopping list item.
Line 29: we call the delegate method addShoppingListItem with the shopping item as a pa-
rameter.
Run the app and try adding a new shopping list item.
You can download the source code for this app from http://bit.ly/2Pvh4N0
51
4
Driving Route and Distance
In this app we will let the user search for a route between two points. If there is a route
available, we will get the distance and draw the route on the map. We will have two text
fields. One for source and another for destination. A search button and a label to display
the distance. We will also have a map to display the route. We will learn how to work with
MapKit, search for addresses, and draw routes. The final project will look similar to the fol-
lowing.
52
Open Xcode and start a new Single View App project. Name the project Driving Route
and Distance.
First, let’s change the background color. Open Main.storyboard and select the view in the
view controller.
Go to the attributes inspector and change the background color to gray or any other color
you like.
Drag two text fields from the object library to the view controller (If you are not sure how to
do this, go back to chapter 2 for review.) Put them next to each other at the top of the view
controller. Select the first text field, go to the attributes inspector and change the place-
holder text to “Start”.
53
Change the placeholder text for the second text field to “Destination”
Drag a button from the object library and change its title to “Search” by double clicking on
the button. Position the button under the text fields. Drag a label from the object library
and position it under the search button. Change the text of the label to “Distance:” Lastly,
find a Map Kit View in the object library and drag it to the view controller. Position it under
the distance label. Your view controller should look similar to the following.
54
Let’s start embedding all the elements in stack views so it looks nice on all device sizes.
Select the two text fields and click on the ember in button and select Stack View.
We should rename the stack view in the document outline to be able to distinguish be-
tween different stack views. Double click on the name and change it to “Text Fields Stack
View”
55
With the Text Fields Stack View selected go to the attributes inspector and change the dis-
tribution to fill equally and the spacing to 8.
Next, select all the elements (text fields stack view, button, label, and map view) and em-
bed them in a stack view. Unlike the first stack view which was horizontal this will be verti-
cal. Select the newly created stack view and set the spacing to 8. Alignment and distribu-
tion should be set to fill.
56
We need to set the auto layout constraints so the stack view stretches to the edges of the
screen. Select the stack view and click the add new constraints button (lower right corner
of Xcode) Set the top, left, bottom, right spacing to 8 and click on the button “Add 4 Con-
straints”
57
This will stretch the stack view to the edges of the screen, but since we set the distribution
to fill, the stack view till try to stretch all elements to fill the space. We don’t want this to
happen for the text fields, the button, and the label, so we need to set their content hug-
ging priority. This tells auto layout to only stretch views with low content hugging priority
value. Select the two text fields, the button, and the distance label and go to the size in-
spector. Set the vertical content hugging priority to 1000.
58
Auto layout will only stretch the map view to fill the stack view since it still has a low con-
tent hugging priority of 250. Run the app in the simulator and it should look similar to the
following.
Lets create outlets for the text fields, the label, and the map view so we can get and set
data for those objects. Name the outlets “startTextField”, “destinationTextField”, “distan-
ceLabel”, and “mapView”. Also, create an action “searchTapped” for the button (If you are
not sure how to create outlets and actions, go back to chapter 2 to review.) This is what
ViewController.swift would look like after you are done creating the outlets and action.
59
What we need to do when the user taps the search button is to read the values from the
text fields for the start and destination points. Then we will try to convert the addresses to
CLPlacemark objects which we will use to look up the route in map kit. We will need to im-
port CoreLocation and MapKit for this. Add them under the import UIKit line in
ViewController.swift
60
Let’s implement the searchTapped method.
on line 31 we use the CLGeocoder to get the geographic coordinates from the address we
submitted in the text field.
61
on line 38 we call another method geocodeDestination( ) to get the geographical coordi-
nates for the destination field. We have to do it in two steps like this because CLGeocoder
would not allow us to search for two coordinates at the same time. Let’s implement geo-
codDestination method.
This method is pretty similar to the previous one but this time it looks up the destinatio
text field. If its able to find a placemark for that address it stores it in destinationPlace-
mark and calls the calculateDistance( ) method. Where we will make a request to calcu-
late the route for these two points. Let’s add calculate distance to ViewController.swift
62
on line 62 check if we have both a source and destination placemark set.
on line 79 we zoom on the map where the route is being displayed with some padding on
the edges.
The overlaying of objects on the map is handled by a MKOverlayRenderer. The map asks
for this object its delegate method mapView(_ mapView: MKMapView, rendererFor overlay:
MKOverlay) so we need to make ViewController.swift implement MKMapViewDelegate
63
methods and set the class as a map view delegate. Change the class definition to the fol-
lowing.
This method just returns a renderer object to the map view for display. Don’t forget the set
the delegate for the map view. Open Main.storyboard, control + drag from the map view
to the view controller. When the pop up appears select delegate outlet.
You can run the app at this point command + R and test it out.
As an exercise try printing an alert message to the user if there is an error finding an ad-
dress and ask them to try using a different address.
You can download the source code for this app from http://bit.ly/2Pvh4N0
64