Você está na página 1de 10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

SwiftTutorialPart2:ASimpleiOSApp
Ray Wenderlich on June 14, 2014

Welcome back to our Swift tutorial series!


In the first Swift tutorial, you learned the basics of the Swift
language, and created your very own tip calculator class.
In this second Swift tutorial, you will learn how to make a simple
iOS app. Specifically, you will create a user interface for your tip
calculator class that you developed last time.
I will be writing this tutorial in a manner so that it is useful for
both complete beginners to iOS, and seasoned iOS developers
transitioning to Swift.
For this Swift tutorial, you will need the latest copy of Xcode
(Xcode 6-Beta at the time of writing this Swift tutorial). You do not
need any prior Swift or Objective-C experience, but it would help
if you had some prior programming experience.

Note: At the time of writing this tutorial, our understanding is


we cannot post screenshots of Xcode 6 since it is still in beta.
Therefore, we are suppressing screenshots in this Swift
tutorial until we are sure it is OK.

Create a simple iOS app in this Swift


tutorial!

GettingStarted
Start up Xcode and go to File\New\Project. Select iOS\Application\Single View Application, and click Next.
Enter TipCalculator for the Product Name, set the Language to Swift, and Devices to iPhone. Make sure Use Core
Data is not checked, and click Next.
Choose a directory to save your project, and click Create.
Lets see what Xcode has built for you. In the upper left corner of Xcode, select the iPhone 5 Simulator and click Play
to test your app.
You should see a blank white screen appear. Xcode has created a single blank screen in your app; in this tutorial youll
fill it up!

CreatingYourModel
First things first before you create the user interface for your app, you should create your apps model. A model is a
class (or set of classes) that represents your classs data, and operations that your app will perform on that data.
In this tutorial, your apps model will simply be the TipCalculatorclass you created in the first Swift tutorial,
http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

1/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

except you will rename it to TipCalculatorModel.


Lets add this class to your project. To do this, go to File\New\File and select iOS\Source\Swift File. Name the file
TipCalculatorModel.swift, and click Create.

Note: You cannot call code from your app that resides in a Playground file. Playground files are just for testing
and prototyping code; if you want to use code from a Playground in your app, you have to move it to a Swift file
like youre doing here.

Open TipCalculator.swift, and copy your TipCalculatorclass from the previous tutorial into the file, and make
the following changes:
1. Rename the class to TipCalculatorModel
2. Change totaland taxPctfrom constants to variables (because the user will be changing these values as
he/she runs the app)
3. Because of this, you need to change subtotalto a computed property. Replace the subtotalproperty
with the following:
var subtotal: Double {
get {
return total / (taxPct + 1)
}
}
A computed property does not actually store a value. Instead, it is computed each time based on other values. Here,
you calculate the subtotal each time it is accessed based on the current values of totaland taxPct.

Note: You can also provide a setter for a computed property if youd like, with syntax like this:
var subtotal: Double {
get {
return total / (taxPct + 1)
}
set(newSubtotal) {
//...
}
}
Your setter would update its backing properties (i.e. set totaland taxPctbased on newSubtotal), but that
wouldnt make sense for this app, so youre not implementing it here.

4. Delete the line that sets subtotalin init


5. Delete any comments that are in the file
When youre done, the file should look like this:
import Foundation
class TipCalculatorModel {
var total: Double
var taxPct: Double
var subtotal: Double {
http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

2/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

get {
return total / (taxPct + 1)
}

init(total:Double, taxPct:Double) {
self.total = total
self.taxPct = taxPct
}
func calcTipWithTipPct(tipPct:Double) -> Double {
return subtotal * tipPct
}
func returnPossibleTips() -> Dictionary<Int, Double> {
let possibleTipsInferred = [0.15, 0.18, 0.20]
let possibleTipsExplicit:Double[] = [0.15, 0.18, 0.20]
var retval = Dictionary<Int, Double>()
for possibleTip in possibleTipsInferred {
let intPct = Int(possibleTip*100)
retval[intPct] = calcTipWithTipPct(possibleTip)
}
return retval
}
}
You have your apps model ready to go time for the views!

IntroductiontoStoryboardsandInterfaceBuilder
Note: If you are a seasoned iOS developer, this section and the next may be review. To speed things up, you
might want to skip forward to the section titled A View Controller Tour. Well have a starter project waiting for
you there with the user interface for the app pre-created.

You create the user interface for your iOS apps in something called a Storyboard. Xcode comes with a built-in tool
called Interface Builder that allows you to edit Storyboards in a nice, visual way.
With Interface Builder, you can lay out all of your buttons, text fields, labels, and other controls in your app (called
Views) as simply as dragging and dropping.
Go ahead and click on Main.storyboard in the left side of Xcode to reveal the Storyboard in Interface Builder.
Theres a lot of stuff to cover here, so lets go over each section of the screen one at a time.
1. On the far left is your Project Navigator, where your can see the files in your project.
2. On the left of Interface Builder is your Document Outline, where you can see at a glance the views inside
each screen of your app (view controllers). Be sure to click the down arrows next to each item to fully expand
the document outline.
Right now your app only has one view controller, with only one empty white view. Youll be adding things into this
soon.

http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

3/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

3. Theres an arrow to the left of your view controller. This indicates that this is the initial view controller, or the
view controller that is first displayed when the app starts up. You can change this by dragging the arrow to a
different view controller, or by clicking the Is Initial View Controller property on a different view controller in the
Attributes Inspector (more on Inspectors later).
4. On the bottom of the Interface Builder youll see something that says w Any, h Any. This means that you
are editing the layout for your app in a way that should work on any sized user interface. You can do this through
the power of something called Auto Layout. By clicking this area, you can switch to editing the layout for devices
of specific size classes. Youll learn about Adaptive UI and Auto Layout in a future tutorial.
5. On the top of your view controller youll see three small icons, which represent the view controller itself and
two other items: First Responder, and Exit. If youve been developing in Xcode for a while, youll notice that these
have moved (they used to be below the view controller). You wont be using these in this tutorial, so dont worry
about them for now.
6. On the bottom right of Interface Builder are four icons related to Auto Layout. Again, youll learn more about
these in a future tutorial.
7. On the upper right of Interface Builder are the Inspectors for whatever you have selected in the Document
Outline. If you do not see the inspectors, go to View\Utilities\Show Utilities.
Note there are several tabs of inspectors. Youll be using these a lot in this tutorial to configure the views you
add to this project.
8. On the bottom right of Interface Builder are the Libraries. This is a list of different types of views or view
controllers you can add to your app. Soon you will be dragging items from your library into your view controller
to lay out your app.

CreatingyourViews
Remember that your TipCalculatorModelclass has two inputs: a total, and a tax percentage.
It would be nice if the user could type in the total with a numeric keyboard, so a text field is perfect for that. As for the
tax percentage, that usually is restricted to a small range of values, so youll use a slider for that instead.
In addition to the text field and slider, you will need a label for each, a navigation bar to show the apps name, a button
to click to perform the tip calculation, and a text field to show the results.
Lets build this user interface one piece at a time.
1. Navigation bar. Rather than adding a navigation bar directly, select your view controller and go to
Editor\Embed In\Navigation Controller. This will set up a Navigation Bar in your view controller. Double click
the Navigation Bar (the one inside your view controller), and set the text to Tip Calculator.
2. Labels. From the Object Library, drag a Label into your view controller. Double click the label and set its text to
Bill Total (Post-Tax):. Select the label, and in the Inspectors fifth tab (the Size Inspector), set X=33 and Y=81.
Repeat this for another label, but set the text to Tax Percentage (0%):, X=20, and Y=120.
3. Text Field. From the Object Library, drag a Text Field into your view controller. In the Attributes Inspector, set
Keyboard Type=Decimal Pad. In the Size Inspector, set X=192, Y=72, and Width=268.
4. Slider. From the Object Library, drag a Slider into your view controller. In the Attribute Inspector, set Minimum
Value=0, Maximum Value=10, and Current Value=6. In the Size Inspector, set X=190, Y=111, and Width=272.
5. Button. From the Object Library, drag a Button into your view controller. Double click the Button, and set the text
to Calculate. In the Size Inspector, set X=208 and Y=149.
6. Text View. From the Object Library, drag a Text View into your View Controller. Double click the Text View, and
delete the placeholder text. In the Attributes Inspector, make sure Editable and Selectable are not checked. In
http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

4/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

the Size Inspector, set X=20, Y=187, Width=440, and Height=288.


7. Tap Gesture Recognizer. From the Object Library, drag a Tap Gesture Recognizer onto your main view. This will
be used to tell when the user taps the view to dismiss the keyboard.
8. Auto Layout. Interface Builder can often do a great job setting up reasonable Auto Layout constraints for you
automatically; and it definitely can in this case. To do this, click on the third button in the lower left of the
Interface Builder (which looks like a Tie Fighter) and select Add Missing Constraints.
Build and run on your iPhone 5 simulator, and you should see a basic user interface working already!

AViewControllerTour
Note: If you skipped ahead to this section, here is a zip of the project at this point.

So far youve created your apps models and views its time to move on to the view controller.
Open ViewController.swift. This is the Swift code for your single view controller (screen) in your app. It is
responsible for managing the communication between your views and your model.
You will see that the class has the following code in it already:

// 1
import UIKit
// 2
class ViewController: UIViewController {
// 3
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
// 4
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
There are some new elements of Swift here that you havent learned about yet, so lets go over them one at a time.
1. iOS is split up into multiple frameworks, each of which contain different sets of code. Before you can use code
from a framework in your app, you have to import it like you see here. UIKit is the framework that contains the
base class for view controllers, various controls like buttons and text fields, and much more.
2. This is the first example youve seen of a class that subclasses another class. Here, you are declaring a new
class ViewControllerthat subclasses Apples UIViewController.

Note: Experienced iOS developers note that you do not have to put a class prefix on your class names like you
did in Objective-C to avoid namespace collisions (i.e. you dont have to name this RWTViewController). This
is because Swift has namespace support, and the classes you create in your project are in their own namespace.
To see what I mean, replace the class declaration with the following:
http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

5/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

class UIViewController {
}
class ViewController: UIKit.UIViewController {
Here UIKit.UIViewControllerrefers to the UIViewControllerclass in the UIKitnamespace.
Likewise, TipCalculator.UIViewControllerwould refer to the the UIViewControllerclass in your
project.

3. This method is called with the root view of this view controller is first accessed. Whenever you override a method
in Swift, you need to mark it with the overridekeyword. This is to help you avoid a situation where you
override a method by mistake.
4. This method is called when the device is running low on memory. Its a good place to clean up any resources you
can spare.

ConnectingyourViewControllertoyourViews
Now that you have a good understanding of your view controller class, lets add some properties for its subviews, and
hook them up in interface builder.
To do this, add these following properties to your ViewControllerclass (right before viewDidLoad):
@IBOutlet var totalTextField : UITextField
@IBOutlet var taxPctSlider : UISlider
@IBOutlet var taxPctLabel : UILabel
@IBOutlet var resultsTextView : UITextView
Here you are declaring four variables just as you learned in the first Swift tutorial a UITextField, a UISlider, a
UILabel, and a UITextView.
Theres only one difference: youre prefixing these variables with the @IBOutletkeyword. Interface Builder scans
your code looking for any properties in your view controller prefixed with this keyword. It exposes any properties it
discovers so you can connect them to views.
Lets try this. Open Main.storyboard and select your View Controller in the Document Outline. Open the Connections
Inspector (6th tab), and you will see all of the properties you created listed in the Outlets section.
Youll notice a small circle to the right of resultsTexView. Control-drag from that button down to the text view
below the Calculate button, and release to connect your Swift property to this view.
Now repeat this for the other three properties, connecting each one to the appropriate UI element.

Note: Theres another, even easier way to connect views to properties on your view controller.
While you have Main.storyboard open, you would open your Assistant Editor (View\Assistant Editor\Show
Assistant Editor) and make sure the assistant editor is set to display your view controllers Swift code.
Then, you would control-drag from your view into the Assistant Editor, right before viewDidLoad. In the popup
that appears, you would enter a name for a property to create, and click click Connect.
This would create the property for you in your view controller and connect it in Interface Builder, in a single step.
Convenient, eh?
Both ways work; you can choose whichever you prefer for our projects.

http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

6/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

ConnectingActionstoyourViewController
Just like you connected views to properties on your view controller, you want to connect certain actions from your
views (such as a button click) to methods on your view controller.
To do this, open ViewController.swift and add these three new methods anywhere in your class:
@IBAction func calculateTapped(sender : AnyObject) {
}
@IBAction func taxPercentageChanged(sender : AnyObject) {
}
@IBAction func viewTapped(sender : AnyObject) {
}
When you declare callbacks for actions from views, they always need to have this same signature a function with no
return value, that takes a single parameter of type AnyObjectas a parameter, which represents a class of any type.

Note: AnyObjectis the equivalent of idin Objective-C. To learn more about AnyObject, check out our Swift
Language FAQ.

To make Interface Builder notice your new methods, you need to mark these methods with the @IBActionkeyword
(just as you marked properties with the @IBOutletkeyword).
Next, switch back to Main.storyboard and make sure that your view controller is selected in the Document Outline.
Make sure the Connections Inspector is open (6th tab) and you will see your new methods listed in a the Received
Actions section.
Find the circle to the right of calculateTapped:, and drag a line from that circle up to the Calculate button.
In the popup that appears, choose Touch Up Inside:
This is effectively saying when the user releases their finger from the screen when over the button, call my method
calculateTapped:.
Now repeat this for the other two methods:
Drag from taxPercentageChanged:to your slider, and connect it to the Value Changed action, which is
called every time the user moves the slider.
Drag from viewTapped:to the Tap Gesture Recognizer in the document outline. There are no actions to
choose from for gesture recognizers; your method will simply be called with the recognizer is triggered.
Note: Just like with properties, theres a shortcut for connecting actions to methods using Interface Builder as
well.
You would simply control-drag from something that has an action (like a button) into the Swift code for your view
controller in the Assistant Editor. In the popup that appears, you would select Action and give the name of your
method.
This would create a method stub in your Swift file and connect the action to your method in one step. Again, both
ways work so its just a matter of what is convenient to you!

ConnectingYourViewControllertoyourModel
http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

7/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

Youre almost done all you have to do now is hook your view controller to your model.
Open ViewController.swift and add a property for the model to your class and a method to refresh the UI:
let tipCalc = TipCalculatorModel(total: 33.25, taxPct: 0.06)
func refreshUI() {
// 1
totalTextField.text = String(tipCalc.total)
// 2
taxPctSlider.value = Float(tipCalc.taxPct) * 100.0
// 3
taxPctLabel.text = "Tax Percentage (\(Int(taxPctSlider.value))%)"
// 4
resultsTextView.text = ""
}
Lets go over refreshUI one line at a time:
1. In Swift you must be explicit when converting one type to another. Here you convert tipCalc.totalfrom a
Doubleto a String.
2. You want the tax percentage to be displayed as an Integer (i.e. 0%-10%) rather than a decimal (like 0.06). So
here you multiply the value by 100.
Note: The cast is necessary because the taxPctSlider.value property is a Float.
3. Here you use string interpolation to update the label based on the tax percentage.
4. You clear the results text view until the user taps the calculate button.
Next, add a call to refreshUIat the bottom of viewDidLoad:
refreshUI()
Also implement taxPercentageChangedand viewTappedas follows:
@IBAction func taxPercentageChanged(sender : AnyObject) {
tipCalc.taxPct = Double(taxPctSlider.value) / 100.0
refreshUI()
}
@IBAction func viewTapped(sender : AnyObject) {
totalTextField.resignFirstResponder()
}
taxPercentageChangedsimply reverses the multiply by 100 behavior, while viewTappedcalls
resignFirstResponderon the totalTextFieldwhen the view is tapped (which has the effect of dismissing
the keyboard).
One method left. Implement calculateTappedas follows:
@IBAction func calculateTapped(sender : AnyObject) {
// 1
tipCalc.total = Double(totalTextField.text.bridgeToObjectiveC().doubleValue)
// 2
let possibleTips = tipCalc.returnPossibleTips()
var results = ""
// 3
for (tipPct, tipValue) in possibleTips {
// 4
results += "\(tipPct)%: \(tipValue)\n"
http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

8/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

}
// 5
resultsTextView.text = results

Lets go over this line by line:


1. Here you need to convert a Stringto a Double. This is a bit of a hack to do this; hopefully there will be an
easier way in a future update to Swift.

Note: Heres how this works, in case youre wondering.


At the time of writing this tutorial, Swifts Stringclass does not have access to every method that NSString
has (NSStringis the string class in the Foundation framework). In particular, Swifts Stringclass does not
have a method to convert to the string to a double; however NSStringdoes.
You can call bridgeToObjectiveC()method on a Swift Stringto convert it to NSString. Then, you can
call any method that is available on NSString, such as a method to convert to a double.
To learn more about the methods available on NSString, check out the NSString Class Reference.

2. Here you call the returnPossibleTipsmethod on your tipCalcmodel, which returns a dictionary of
possible tip percentages mapped to tip values.
3. This is how you enumerate through both keys and values of a dictionary at the same time in Swift. Handy, eh?
4. Here you use string interpolation to build up the string to put in the results text filed. \nis the newline character.
5. Finally you set the results text to the string you have been building.
And thats it! Build and run, and enjoy your hand-made tip calculator!

Note: @BBK on the forums asked how you would sort the results by tip percentage. I thought that was a great
question, so included the answer here.
Simply replace the for loop in section 3 with the following:
var keys = Array(possibleTips.keys)
sort(keys)
for tipPct in keys {
let tipValue = possibleTips[tipPct]!
let prettyTipValue = String(format:"%.2f", tipValue)
results += "\(tipPct)%: \(prettyTipValue)\n"
}
You can get the keys in a dictionary (in this case, the tip percentages) with keys. They are not guaranteed to be
in any order, so you have to sort them using the built in function sortwhich by default sorts by using the <
operator (so numerical order).
Once you have the sorted keys, you can loop through them and pull out each item in the dictionary with the
dictionary[key]syntax.
As @Solidath points out: "One important addition is that, the possibleTips[] dictionary access returns type Double?,
not simply Double. That is because any Dictionary access (subscripting or using updateValue(forKey:) method) returns
nil when the key is absent. In our case, we are sure that the key will have a value. For this, we put an exclamation
mark "!" at the very end of the tipValue assignment, which is called forced unwrapping."
Also note you truncate the tip value to two percentage points, using an initializer on String that accepts a format
http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

9/10

7/7/2014

Swift Tutorial Part 2: A Simple iOS App | Ray Wenderlich

string (like stringWithFormatin Objective-C). %.2fis a format string that formats a float value as a String,
with 2 decimal places.
I hope this helps! :]

WhereToGoFromHere?
Here is the final Xcode project with all the code from this Swift tutorial.
Want to learn more? Keep reading for the next part of this series, where you'll learn about tuples, protocols, and table
views - or check out our new Swift books!
Thanks for reading this tutorial, and if you have any comments or questions please join in the forum discussion below!

Ray Wenderlich
Ray is an indie software developer currently focusing on iPhone and iPad development,
and the administrator of this site. Hes the founder of a small iPhone development studio
called Razeware, and is passionate both about making apps and teaching others the
techniques to make them.
When Rays not programming, hes probably playing video games, role playing games, or
board games.

http://www.raywenderlich.com/74904/swift-tutorial-part-2-simple-ios-app

10/10

Você também pode gostar