Quantcast
Channel: Kodeco | High quality programming tutorials: iOS, Android, Swift, Kotlin, Unity, and more
Viewing all articles
Browse latest Browse all 4387

Swift Tutorial Part 2: A Simple iOS App

$
0
0
Create a simple iOS app in this Swift tutorial!

Create a simple iOS app in this Swift tutorial!

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 Swift tutorial, it is unclear to us if we are allowed to 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.

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.

Let’s 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 you’ll fill it up!

Creating Your Model

First things first – before you create the user interface for your app, you should create your app’s model. A model is a class (or set of classes) that represents your class’s data, and operations that your app will perform on that data.

In this tutorial, your app’s model will simply be the TipCalculator class you created in the first Swift tutorial, except you will rename it to TipCalculatorModel.

Let’s 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 you’re doing here.

Open TipCalculator.swift, and copy your TipCalculator class from the previous tutorial into the file, and make the following changes:

  1. Rename the class to TipCalculatorModel
  2. Change total and taxPct from 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 subtotal to a computed property. Replace the subtotal property 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 total and taxPct.

Note: You can also provide a setter for a computed property if you’d 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 total and taxPct based on newSubtotal), but that wouldn’t make sense for this app, so you’re not implementing it here.

  1. Delete the line that sets subtotal in init
  2. Delete any comments that are in the file

When you’re done, the file should look like this:

import Foundation
 
class TipCalculatorModel {
 
  var total: Double
  var taxPct: Double
  var subtotal: Double {
    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 app’s model ready to go – time for the views!

Introduction to Storyboards and Interface Builder

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. We’ll 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.

There’s a lot of stuff to cover here, so let’s 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. You’ll be adding things into this soon.

  3. There’s 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 you’ll 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. You’ll learn about Adaptive UI and Auto Layout in a future tutorial.
  5. On the top of your view controller you’ll see three small icons, which represent the view controller itself and two other items: First Responder, and Exit. If you’ve been developing in Xcode for a while, you’ll notice that these have moved (they used to be below the view controller). You won’t be using these in this tutorial, so don’t worry about them for now.
  6. On the bottom right of Interface Builder are four icons related to Auto Layout. Again, you’ll 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. You’ll 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.

Creating your Views

Remember that your TipCalculatorModel class 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 you’ll 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 app’s name, a button to click to perform the tip calculation, and a text field to show the results.

Let’s 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 Inspector‘s 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 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!

A View Controller Tour

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

So far you’ve created your app’s models and views – it’s 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 haven’t learned about yet, so let’s 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 you’ve seen of a class that subclasses another class. Here, you are declaring a new class ViewController that subclasses Apple’s 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 don’t 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.UIViewController refers to the UIViewController class in the UIKit namespace. Likewise, TipCalculator.UIViewController would refer to the the UIViewController class in your project.

  1. 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 override keyword. This is to help you avoid a situation where you override a method by mistake.
  2. This method is called when the device is running low on memory. It’s a good place to clean up any resources you can spare.

Connecting your View Controller to your Views

Now that you have a good understanding of your view controller class, let’s add some properties for its subviews, and hook them up in interface builder.

To do this, add these following properties to your ViewController class (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.

There’s only one difference: you’re prefixing these variables with the @IBOutlet keyword. 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.

Let’s 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.

You’ll 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: There’s 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 controller’s 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.

Connecting Actions to your View Controller

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 AnyObject as a parameter, which represents a class of any type.

Note: AnyObject is the equivalent of id in 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 @IBAction keyword (just as you marked properties with the @IBOutlet keyword).

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, there’s 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 it’s just a matter of what is convenient to you!

Connecting Your View Controller to your Model

You’re 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 = ""
}

Let’s 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.total from a Double to 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 refreshUI at the bottom of viewDidLoad:

refreshUI()

Also implement taxPercentageChanged and viewTapped as follows:

@IBAction func taxPercentageChanged(sender : AnyObject) {
  tipCalc.taxPct = Double(taxPctSlider.value) / 100.0
  refreshUI()
}
@IBAction func viewTapped(sender : AnyObject) {
  totalTextField.resignFirstResponder()
}

taxPercentageChanged simply reverses the “multiply by 100″ behavior, while viewTapped calls resignFirstResponder on the totalTextField when the view is tapped (which has the effect of dismissing the keyboard).

One method left. Implement calculateTapped as 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"
  }
  // 5
  resultsTextView.text = results
}

Let’s go over this line by line:

  1. Here you need to convert a String to 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: Here’s how this works, in case you’re wondering.

At the time of writing this tutorial, Swift’s String class does not have access to every method that NSString has (NSString is the string class in the Foundation framework). In particular, Swift’s String class does not have a method to convert to the string to a double; however NSString does.

You can call bridgeToObjectiveC() method on a Swift String to 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.

  1. Here you call the returnPossibleTips method on your tipCalc model, which returns a dictionary of possible tip percentages mapped to tip values.
  2. This is how you enumerate through both keys and values of a dictionary at the same time in Swift. Handy, eh?
  3. Here you use string interpolation to build up the string to put in the results text filed. \n is the newline character.
  4. Finally you set the results text to the string you have been building.

And that’s it! Build and run, and enjoy your hand-made tip calculator!

Where To Go From Here?

Here is the final Xcode project with all the code from this Swift tutorial.

Stay tuned for a bunch more Swift tutorials. We’ll be showing you how you can work with table views, Sprite Kit, some iOS 8 APIs, and much more!

In the meantime, if you want to learn more here are some great resources to check out:

Thanks for reading this tutorial, and if you have any comments or questions please join in the forum discussion below!

Swift Tutorial Part 2: A Simple iOS App is a post from: Ray Wenderlich

The post Swift Tutorial Part 2: A Simple iOS App appeared first on Ray Wenderlich.


Viewing all articles
Browse latest Browse all 4387

Trending Articles