Unit 17: Actions & Outlets Flashcards
Action
connects a method in source code and a control in Interface Builder
the connects allows particular code to run when a user interacts with the app’s controls
e.g., a certain method may be associated with an action, such as a button tap or a switch change
CGFloat
a type of number that can have a decimal point, such as 3.5, 7.0, or -5.5; interacts with UIColor (a common type)
Enabled
a button or control is available for interaction
Disabled
the user can still see the UI element, but touching or otherwise trying to activate the control will yield no effect on the app; appears slightly dimmed
Outlet
connects a variable in source code to an object in the storyboard; the connection allows the code to access those objects and get information or make changes when the app is running
Slider
a type of control in the UI that enables the user to select a single value between a minimum and maximum number
Switch
control that acts like an on/off button (like Airplane Mode or Bluetooth in the Settings app
There are two kinds of connections between storyboards and code:
Outlets connect variables in your code to objects in the storyboard, so you can access those objects within your code and get information or make changes when the app is running.
Actions connect controls like switches and buttons to methods in your code, so tapping a button, for example, will run a particular method.
Creating Outlets
When you develop an app, you want your code to refer to objects in a storyboard. To do this, you must make connections, called outlets, between the two.
In this part, you’ll add a view to the user interface, define and connect an outlet that connects to the view, and use the outlet you defined to set the background color of the view in code. When you’re done, the app will look like the image to the left.
Follow these steps to get started
Create a new Xcode project using the Single View Application template:
“1. Name the app “ColorMix” and fill in the rest of the details:
“2. Using the project navigator, open Main.storyboard.
“3. Find a view in the Object library. Remember you can use the Filter field to narrow down the list of options.
“4. Drag the view onto the View Controller Scene. Use the guides to align it to the top of the scene and center it horizontally.
5. A white view on a white background is hard to see. Choose Editor > Canvas > Show Bounds Rectangles to display an outline of everything on the scene.
6. Open the assistant editor by going to View > Assistant Editor > Show Assistant Editor. If you can’t see ViewController.swift in the assistant editor, make sure the jump bar at the top of the assistant editor looks
like this:
Control-drag (hold down the Control key, then click and drag with the mouse or trackpad) from the view into the code.
Enter “colorView” in the Name field and click Connect
Here’s what you’re seeing, from left to right:
Circles: The filled circle indicates that the outlet is connected. If the outlet wasn’t connected, it would be an empty circle.
@IBOutlet weak: This signals to Xcode that the property on this line is an outlet.
var colorView: This is the declaration of a property you’re already familiar with.
: UIView!: The type of the property is UIView!. The exclamation point means that if the outlet is not connected and you try to access this property, your app will crash. UIView is the basic view type used in all iOS apps. Almost everything you see on the screen is a kind of UIView, which
is responsible for drawing and handling touches.
The important thing to remember is that when you use colorView in the ViewController.swift code, you’re referring to the view you’ve just added to your storyboard.
Find the function viewDidLoad(). As you learned when printing to the console from the SinglePhoto app, this function is called when your view controller is ready to appear on the screen. Add the following code inside the function:
colorView.backgroundColor = .black
When the items from the storyboard have all been created and the outlets and actions have all been connected…
…viewDidLoad() is called. The code above sets the background color of the view to black. The view you see in the storyboard doesn’t change color, because the code isn’t run until the
app is run.
In the device menu, choose the iPhone 6s simulator, then build and run the app. You’ll see a black rectangle at the top of the screen.
Disconnected Outlet or Action—Fixing a Crash
Sometimes you’ll build and run your app with no errors, but the app immediately crashes on launch. Your device (or the simulator) shows your Home screen with an error in the console, like this:
“*** Terminating app due to uncaught exception ‘NSUnknownKeyException’, reason: ‘[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key someNameFromYourApp”
The error message doesn’t tell you that the problem actually stems from a view in Interface Builder, but that’s exactly where you need to look.
Open the storyboard and select View Controller…
…either in the document editor or by selecting the yellow circle at the top of the main editor in Interface Builder.
Now open the Connections inspector on the right side of the screen. The Connections inspector lists all the outlet and action connections for the selected view controller.
If you look carefully at the list of outlets, you’ll notice that most connections have either an empty circle or a filled-in circle, just like the circles you see in the gutter of a Swift file with IBOutlets or IBActions. One connection, though, displays an exclamation point instead—and that’s the source of the crash.
Imagine that in this case…
…you created an outlet from Interface Builder to the Swift code file, but entered bleuSlider as its name instead of blueSlider. After creating the outlet, you noticed the typo, fixed it, and made sure the slider was hooked up to the new name.
Interface Builder project
But that adjustment won’t fix the problem. You need to go back to Interface Builder to inform the storyboard about the outlet’s new name. Without that step, the mismatch won’t be discovered until the app launches and tries to hook up all its connections—at which point, the storyboard file will try to open a connection to a name that no longer exists. And your app will crash.
You can remove invalid connections by clicking the “x” next to the element’s name. (You can remove valid connections this way, too.) Once you’ve removed all invalid connections, this mysterious error will no longer crash your app on launch.
Creating Actions
To make buttons, switches, and other controls useful in an app, something has to happen when the user interacts with them. This is done by creating actions, which run your code when the user does something. For example:
When the value of a switch is changed (from off to on, or from on to off)… call switchChanged(_:)… on this ViewController.
In this part, you’ll add a UISwitch control. You’ll define an action method and connect it to the switch. When the switch is tapped, your code will change the color of the color view. When you’re done, your app will look
like the image to the left.
Follow the steps below to create an action:
In Xcode, open Main.storyboard.
Find a switch in the Object library…
and drag it onto the scene. Use the guides to center it horizontally and vertically:
In the Attributes inspector, set the Value of the switch to Off:
Open the assistant editor so that ViewController.swift is visible.
Control-drag from the switch into the code file, and release.
Choose Action from the Connection pop-up menu.
Enter “switchChanged” in the Name field.
Enter “UISwitch” in the Type field.
The pop-up menu should look like this:
Click Connect.
A new method is created for you inside the ViewController class. It looks much like other functions and methods you’ve seen and created, with a
few additions.
Here are some details, from left to right:
Circles: The filled circle indicates that the action is connected.
@IBAction: This line signals to Xcode that the method on this line is
an action connected to a control in Interface Builder.
sender: The sender argument is the instance that sent the action.
You chose the type of switch, UISwitch.
Add the following code inside the method:
colorView.backgroundColor = .red
Checkpoint
Build and run the app. When you turn the switch on, the view changes to red. But when you turn it off, it stays red. What’s going on? This is because the action method is called every time the value of the switch changes, and the action method always sets the background color to red.
To make the switch behave like a real switch, delete the line you added above and add the following code:
if sender.isOn {
colorView.backgroundColor = .red
} else {
colorView.backgroundColor = .black
}
isOn is a Bool property of UISwitch that describes if the switch is on or not. The updated version of this method now checks the state of the switch (which is available as the sender argument of the function) and sets the color appropriately.
Multiple Actions and Outlets
When you see color on the screen, you’re actually seeing three components: red, green, and blue. In this part of the lesson, you’ll add two more switches to the app, so you’ll have one switch for red, one for green, and one for blue. Switching each one on or off will add that color component to the color displayed on the screen.
To make this work, you’re going to need to create outlets for each switch so that the isOn property of each switch can be checked when creating the color to be displayed. At the end, the app will look like the image to the left.
Follow these steps to add the new switches:
Open Xcode and go to Main.storyboard.
Select the switch.
Type Command-D to duplicate the switch. Drag it underneath the first one, using the guides to line them up.
Repeat step 3 to add a third switch.
Open the assistant editor to show ViewController.swift.
Control-drag from each switch to the code file to create outlets.
Call them redSwitch, greenSwitch, and blueSwitch.
A common technique is to…
…connect outlets and actions to the same object. Select the top switch and open the Connections inspector in the utilities area.
The image to the left shows all of the outlets and actions the selected switch is connected to.
In Sent Events, you can see that the Value Changed event is linked to switchChanged: in ViewController. Although you could link to the other events, only the Value Changed event is sent when a switch is switched.
Referencing Outlets shows that the switch is referenced by redSwitch in ViewController.
Select the middle switch and look at the Connections inspector. Because
you duplicated the switches instead of adding new ones, they’re already connected to the switchChanged action.
Follow these steps to learn another way to connect actions.
In the Connections inspector, click the X by the Value Changed event.
This will disconnect that switch from the action.
In the ViewController.swift file in the assistant editor, find the circle icon in the gutter next to the action method. When you mouse over it,
the red switch and blue switch will be highlighted in the storyboard to indicate that they’re connected.
Next steps [cont’d]
The pop-up menu should look like this: There are many ways to connect outlets and actions.
Control-dragging from the storyboard to code creates new outlets and actions. Once they’re
in place, they can be connected, disconnected, and reconnected either
from the Connections inspector or using the circle icons in code files.
Which is better? Use the Connections inspector if you want to know which outlets and actions a particular object in the storyboard is connected to. Use the circle icons in code if you want to know which objects a particular outlet or action is connected to.
Now that you’ve created the user interface and connected all the outlets
and actions, it’s time to write the code.
The action method is not the best place to update the color of the view. There’s already some repeated code in the file: The color is set to black in viewDidLoad and again when the switch is turned off. A better design is
to create a single function that makes the correct color based on the state
of each switch, and to call this both from the action method and from[…]”
“Add the following code to the ViewController class: func updateColor() { var red: CGFloat = 0 var green: CGFloat = 0 var blue: CGFloat = 0 if redSwitch.isOn { red = 1 } if greenSwitch.isOn { green = 1 } if blueSwitch.isOn { blue = 1 } let color = UIColor(red: red, green: green, blue: blue, alpha: 1) colorView.backgroundColor = color } This method starts with three variables representing the red, green, and blue components of a color, initialized to zero. It checks each switch value and sets the component to 1 if the switch is on. ”
“Finally, a color is created from the components, and the color of the colorView is set. To update the action method to call this new function, remove the code that was setting the color and replace it with the single line updateColor(). From viewDidLoad(), remove the line that was setting the color and replace it with updateColor(). Build and run the application. Change each of the switches, and you’ll see the colors mix together.
Sliders
Your three switches now control the three components that make up a color, but you only end up with eight possible colors. In this part of the lesson, you’ll add slider controls, like the brightness or volume sliders on an iOS device, to provide finer control over colors. At the end, your app will look like this image to the left.
First, you need to make some room in the interface for the sliders. You could put them all underneath the switches, but it would make more sense for the slider to be next to the switch that controls it. So you need to move all the switches to the left, space them out a little, then add a slider next to each switch.
Follow these steps:
Select all three switches by Shift-clicking each one or by dragging a selection box around them.
Drag the group of switches over to the left and up, so that the central switch is vertically centered in the scene and all three switches are aligned to the left margin guide.
Sliders [con’t]
Select the top switch only, then hold down the Shift key and press the Up Arrow key four times to move it farther from the central switch.
Select the bottom switch, then hold down the Shift key and press the Down Arrow key four times to move the switch farther down.
Why add space between the switches? At the moment, you’re using the simulator with a cursor, which allows you to hit a very small object with precision. But when you’re using a device with your finger, you need more room around interface elements.
Follow these steps to add the sliders:
Find a slider in the Object library and drag it onto the scene. Using the guides, align it vertically with the top switch and horizontally within the scene.
Repeat this for the other switches, so each switch has a slider next to it. The scene should look like this: