Daily Word App — iOS #6
It’s time to put what we’ve learned so far into action and build a little app that actually does something semi-useful. We’re going to make an app that will show an amazing new word every time you open the app … not the most awesome idea you’ve ever heard but it will allow us to do a few things that you’ll use in the future:
- Store information in variables and arrays.
- Display and change information on screen.
- Carry out actions when users tap on buttons.
- Use images that we import into the app.
- Write some basic logic — by making choices using if statements.
and more!
Design first
Always have an idea of what the app will look like before you start coding. Here’s the end result of what we’re building, taken directly as a screenshot from the Storyboard in Xcode.
Not the most graphically amazing of apps, but it’ll do for this tutorial.
Design also means UX
Design is not just how it looks, but how the user uses it (UX — user experience), so we also need to define at the design stage how it’s going to work:
- When the app is opened, a word will appear on screen e.g. Féileacáin above (the Irish for butterfly, just a beautiful word!)
- When the user hits Go, the word will change.
- When the user hits any of the Irish, English or French buttons, the word will change to that language and the next time the Go button is tapped, the new word will be in that language.
Create a new project in Xcode
Let’s get started — open Xcode and hit “Create a New XCode Project”:
Pick a Single View Application and hit Next:
- Type in a Product Name — I choose “Daily Word” here.
- For Organization Name, put anything you want
- Likewise for Organization Identifier put something in the format <what>.<ever>.com. This is important later when you’re publishing apps, but not for now.
- Make sure the Language is Swift and Devices is iPhone.
Then bang on Next:
Pick somewhere to save it on your Mac, and hit Create:
and Xcode should open a new project:
Cool. Head straight to the Main.storyboard (click on it in the Project Explorer on the left-hand panel):
First thing we’ll do is create our user interface — what the user will see on screen. It’s a simple app with only one screen, so won’t take too long.
There should be one View Controller already in the Storyboard — this is basically “the screen”. To put objects onto it we can either create them with code, in the corresponding ViewController.swift file, or we can drag them out from the Object Library and place them on screen.
Type in the Filter box to find the objects you’re looking for. First thing we’ll search for is a Label:
Drag the label out and position it at the top of the View Controller. This will be for our “Daily Word” title.
If you click on the Label, you can re-size it by dragging out the sides — make it the full width of the screen and increase the height, as we’re going to increase the size of the text aswell in a moment:
Now we’re going to change the attributes of the Label by clicking on it — and changing a few things via the Attribute Inspector; this is the 4th tab on the right-hand panel:
First, change what the Label says, by changing “Label” to “Daily Word” (after you type it, hit return for it to take affect):
Now we want to centre the text — use the Alignment buttons, just like you would in Microsoft Word:
Now make the text size larger, by hitting the little up arrow a few times, beside where it says Font:
Now we want to change the background color of the Label. Scroll down the Attributes Inspector until you see Background:
By default, it makes the background transparent — so all you see is the text itself. If you click on the blue arrows to the right, this colour selection box will pop up:
You can see the Recently Used Colors — this will probably be empty for you, if you haven’t used any recently! So to get the colour you want hit Other at the bottom of the box. This will open this:
Ooh, nice! You can click on that circle to pick a color, or if you know exactly what you want in RBG or Hex values (how colors are defined, just Google ‘Hex colors’ to find out more!), hit the 2nd tab on the box:
I know that the color I want has a Hex value of 2ECC71. So I copy that into the box beside Hex Color # and then I click on the color itself as shown on the bottom left of the box. Once I click on it, the background color of the Label will change:
Ok, now you know how to change colors manually! We could also do this with code ( “programmatically”) but no need for that right now.
Now let’s drag out another label onto the View Controller:
Just like before, resize it, centre align the text and make the font size even bigger:
Great. Now we need to add our “Go” button and our three buttons — for Irish, English and French. Filter the Object Library for Button:
Drag a Button out onto the View Controller:
We’re going to use an image for this button, instead of text. First we need to import an image into the app. In the Project Explorer, click on Assets.xcassets — this is where we store images for the app.
For the Go button, I downloaded a icon from icons8.com. To add it to the Assets folder, just drag it from the Finder on your Mac to panel where it says Appicon:
Note that it says 1x under the image and that there are two other slots — 2x and 3x. This is for including the same image in different sizes, to cater for iOS devices with different screen sizes / resolutions. No need to worry about it now, but that’ll be important whenever we get serious about making our apps look incredible on any device.
Anyway, now that the image is in the Assets folder, we can go back to the Storyboard and use it for our Button. Click on the Button and then in the Attributes Inspector, delete the word “Button” as we’re using an image instead:
and then click on the Image field and type the name of your image. Once you hit return, the Button will use the image:
Now drag out three more buttons and resize and position them to match our original design:
In the Attributes Inspector, change the Background color to whatever you want:
Note that if you select all three button at the same time (by holding the Command key down and clicking on each button), you can change the colour of all three at the same time.
The text colour is hard to read now, so scroll back up the Attributes Inspector and change it to black or white in the Text Color field, along with increasing the text font size in the Font field:
I then change the text of each button, so they say Irish, English and French:
Ok, cool, you now should have something that looks like this:
That’s our design, but now we have to hook up some code to that big Label and the four Buttons.
Open the Assistant Editor — by hitting the little button that looks like two circles:
This opens up the ViewController.swift file that corresponds to the View Controller we’ve been working on:
If the code file displayed doesn’t look like the right one, click on the Automatic tab at the top and select the correct one.
Outlets and Actions
Now we’re going to add Outlets and Actions. Outlets are special variables that are linked to objects on the View Controller. They can be used to change the objects via code. Likewise, Actions are special functions that are also linked to objects on the View Controller.
To add an Outlet, Control-Drag from the object onto the code file. That means hold down the control key, click on the Button and drag the cursor — you’ll see a line that you can “drop” onto the code file. Make sure you drop it inside the brackets of the main class, but outside of any functions.
When you “drop” the blue line, this dialog box will appear:
For the buttons, click on the Connection field to change Outlet to Action. Give it a meaningful name, like “onGoButtonClick” — this will be the name of the action function created when you hit Connect:
Side-note: when you’re naming variables, functions or classes, it’s best to give them meaningful names i.e. names that relate to their actually meaning. For example, a variable to store your age, call it something like myAge. It will make reading the code much easier for you or others later on.
Ok, hit Connect and you should see the function magically appear:
If we were more excitable, we might now say OMG. Anyway, that new function will be run whenever the user hits the Go button; it doesn’t actually do anything as we need to add more code, but we’ll get to that shortly.
Ok, add three more Action functions for the Irish, English and French buttons (remembering to select Action, not Outlet), resulting in:
If you want to check which Action functions are linked to which Buttons, you can click on a button and then look at the Connections Inspector; this is the 6th tab on the right-hand panel:
We can see from the above screenshot that the French button is connected to the onFrenchButtonClick function. If we wanted to break the link, we could hot the little x beside the function name.
Ok, so now we’ve four (empty) functions for the four buttons. We also need to create an Outlet variable for the main Label, as we’ll be changing that to show the Daily Word.
Control-drag from the Label and call it something meaningful, like wordLabel. This time, choose Outlet, not Action:
This should result in:
Great, we can now use that variable to change the Label on screen, via code. How do we do that? If you remember from the previous tutorials, a Label in actually called UILabel — which is a Class in the iOS SDK. It has various attributes that can be changed, such as the text attribute.
So the change the Label’s text we write:
wordLabel.text = "Whatever"
Where to put that though? We can put it in the viewDidLoad function, this gets ran everytime that View Controller is loaded on screen e.g.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib. wordLabel.text = "Whatever"
}
Note that I’ve put the extra code before the closing bracket:
}
of viewDidLoad, but after the
super.viewDidLoad()
If you do that and then run the app, you should see:
Creating functions
Nice. We now can change that word, just as we wanted! However — we’ll also want to change it whenever any of the four buttons are clicked, so does that mean we’ll be repeating that line of code four times?
Good coding is all about eliminating unnecessary code — so anywhere you have repeated code, a function may be a good alternative. Let’s create a new function, that we will use to set the label’s text. Once it’s created, we can “call” that function elsewhere in our code.
Inside the main Class, but before the final closing bracket, we type:
func setWordLabel(){}
This is a function called setWordLabel that takes no parameters and returns no value. We can now type in between the function’s curly brackets:
wordLabel.text = "Whatever"
i.e.
func setWordLabel(){
wordLabel.text = “Whatever”
}
We now replace the wordLabel.text = “Whatever” in viewDidLoad with
setWordLabel()
which is how we call the function. i.e.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
setWordLabel()
}
If you run that now, you’ll get the same result as before on screen.
Storing list of words in arrays
We have our function to change the Label to say “Whatever” but what we want is for the word to be taken from a list of words — either Irish, English or French.
To store the list, we’ll use some arrays. Inside the main Class, but outside of any functions, declare three arrays, like this:
let irishArray = ["Madra","Coinín","Féileacáin"]let englishArray = ["Dog","Rabbit","Butterfly"]let frenchArray = ["Chien","Lapin","Papillon"]
or to see where it fits in:
These lines of code create three arrays of Strings. Note that we used “let” to create them and not “var” as we don’t intend on changing the arrays.
While we’re here, let’s create a separate String variable, to store what language the user has selected, setting its default to the best language …
var language = "Irish"
Ok, back to our setWordLabel function. We’re going to use some if and else statements to decide what word to use.
func setWord(){ let random : Int = Int(arc4random_uniform(3)) if language == "Irish" {
wordLabel.text = irishArray[random]
}else if language == "English" {
wordLabel.text = englishArray[random]
}else{
wordLabel.text = frenchArray[random]
}
}
Ok, what’s going on?
let random : Int = Int(arc4random_uniform(3))
creates a new variable and stores inside a random number that will be between 0 and 2. We chose between 0 and 2 as we only have 3 items in each array.
arc4random_uniform(3)
is the function we use to generate the random number, it takes in a parameter; the upper limit of the desired number range.
We put it inside a Int() to “cast” the result to the Int Class. Basically to avoid any conflict between different types of numbers. I won’t go into conflicts and casting now, but don’t worry, you’ll encounter plenty of conflicts eventually!
The
if language == "Irish" {
is the start of the if statement. This checks if the variable language is the same as “Irish”.
The
wordLabel.text = irishArray[random]
then sets our Label to be the item in the array irishArray, with the index given by the random variable we created. The rest
}else if language == "English" {
wordLabel.text = englishArray[random]
}else{
wordLabel.text = frenchArray[random]
}
}
checks if the language is English or French and takes the value from the appropriate array. Note that we don’t need a
if language == “French”
at the end, and just have
else{
wordLabel.text = frenchArray[random]
}
instead — as through process of elimination, it has to be French if it’s not Irish or English!
So we now have our function, so our ViewContoller.swift file should look like this:
import UIKitclass ViewController: UIViewController { //to store current language
var language = "Irish" //to store words
let irishArray = ["Madra","Coinín","Féileacáin"]
let englishArray = ["Dog","Rabbit","Butterfly"]
let frenchArray = ["Chien","Lapin","Papillon"] //when go button is clicked
@IBAction func onGoButtonClick(_ sender: Any) {
} //when irish button is clicked
@IBAction func onIrishButtonClick(_ sender: Any) {
} //when english button is clicked
@IBAction func onEnglishButtonClick(_ sender: Any) {
} //when french button is clicked
@IBAction func onFrenchButtonClick(_ sender: Any) {
} @IBOutlet weak var wordLabel: UILabel! override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib. setWordLabel()
} override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
} func setWordLabel(){
let random : Int = Int(arc4random_uniform(3))
if language == "Irish" {
wordLabel.text = irishArray[random]
}else if language == "English" {
wordLabel.text = englishArray[random]
}else{
wordLabel.text = frenchArray[random]
}
}}
Note the lines that start with two forward slashes: //
//to store current language
These are comments — lines of code that won’t be ran. We use them to provide explanations to ourselves (and anyone else looking at our code) about what’s going on. We can also write comments by putting /* in front of some lines and */ afterwards, e.g.
/*
this is a comment.
So is this.
*/
Handily, comments are green so they’re easily distinguishable from other code:
Ok, let’s put in code to those blank button functions. First, we add code to run our setWordLabel function when the Go button is clicked:
//when go button is clicked
@IBAction func onGoButtonClick(_ sender: Any) {
setWordLabel()
}
Now we want to add code to change the language of the word whenever one of the language buttons are clicked. So, if the current word on screen is “Madra” and the user hits the English button, we want the word to change to “Dog”.
To do that, we need to first know what is the current word on screen — or more importantly, what position in its array is the word from.
(italics for dramatic effect!)
You may have noticed that I set the arrays up so each word is at the same index in each different array. So “dog” is at englishArray[0] and it’s Irish translation is at irishArray[0], as is the French translation at frenchArray[0].
This means that if I know the index of a word, I can easily get the translations from the other arrays.
Make sense? We need to keep track of the index of the word — so we create another variable:
var currentIndex = 0
Each time we change the word, we need to change that variable, so add this line to the setWordLabel function:
currentIndex = random
i.e.
Now we can change the word’s language easily, like this:
//when irish button is clicked
@IBAction func onIrishButtonClick(_ sender: Any) {
wordLabel.text = irishArray[currentIndex]
}//when english button is clicked
@IBAction func onEnglishButtonClick(_ sender: Any) {
wordLabel.text = englishArray[currentIndex]
}//when french button is clicked
@IBAction func onFrenchButtonClick(_ sender: Any) {
wordLabel.text = frenchArray[currentIndex]
}
For each language button, we use the value stored in the currentIndex variable to get the word from the relevant array.
And we’re done!! Run the app and you should be able to change the word using all four buttons.
Summary
Ok, so hopefully you got all that working. If you’ve any issues, comment below and I’ll get back to you.
We learnt today how to use variables, arrays, Outlets and Actions to actually do something semi-interesting on screen. It’s the most basic of apps — shows the fundamentals from which you can start to build some more interesting apps.
Please hit the little heart below if you liked this, it’ll help others come across the tutorial, thanks! Andy