Professional Documents
Culture Documents
Getting Started
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!
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.
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.
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.
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:
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.
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\AssistantEditor\Show
AssistantEditor) 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.
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!
}
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 as NSString).doubleValue)
// 2
let possibleTips = tipCalc.returnPossibleTips()
var results = ""
// 3
for (tipPct, tipValue) in possibleTips {
// 4
results += "\(tipPct)%: \(tipValue)\n"
}
// 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.
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 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! :]
RayWenderlich
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.