Sans Pareil Technologies, Inc.

Key To Your Business

Lab 1 - Introduction to Xcode and Interface Builder


In this session, we will create a simple iOS application. We will develop an interactive application that displays the number of times a user clicked on a button. This will illustrate the use of Interface Builder to quickly layout the desired UI components, create outlet and action connections and let Xcode generate the necessary code bindings and stubs for us.

Project

Create a new Xcode project using the option on the splash screen when Xcode starts

  • Select iOS application filter
  • Select the Single View Application project template
  • Use Demo as the Product Name
  • Use Moraine Valley Community College as the Organization Name
  • Use mis124 as the Organization Identifier
  • Use Swift for Language
  • Use Universal for Devices

Interface

We will incrementally develop a simple application that displays a UILabel, UITextField and a couple of UIButton’s which will comprise the contents of our application.

Step 1
  • Select the Main.storyboard file on the left pane of the Xcode window to display the main screen of our demo application in Interface Builder.
  • Drag and drop a Label component from the bottom right pane in the Xcode window to the View Controller displayed in the centre pane of the Xcode window. Double click the label, and set the text to “Number of Clicks:
  • Drag and drop a Text Field component from as above. Select the component in the centre pane, and select the Attributes Inspector pane on the top right pane. Scroll down and de-select the “Enabled” and “User Interaction Enabled” options.
  • Click the “Show the Assistant Editor” button on the button menu at the top-right of the Xcode window. This will display an editor pane in the centre panel with the ViewController.swift file loaded.
  • Control+Click and drag a line from the Label in Interface Builder pane to the editor pane. This will present a popup window which will allow us to create an outlet connection from the storyboard file to the ViewController.swift controller class. Give the outlet a name “text”.
  • In the ViewController.swift file, add a line above the IBOutlet created in the step above for a variable named counter.

var counter = 0

  • Drag and drop a Button component from the Object library pane to the storyboard.
  • Control+Click and drag a line from the button on the storyboard to the ViewController editor. In the popup window change the Connection from Outlet to Action. Specify the name of the function that Xcode generates as increment. Change Arguments from Sender to None. Click the “Connect” button to generate the function that will handle button click events.
  • Add the following code to the body the “increment” function generated by the above step.

counter += 1
NSLog("Clicked %d times", counter)
text.text = "\(counter)"


  • Build and run the application in the simulator.

Step 2
We will update the application to add a reset button which will reset the counter.
  • Drag and drop a Button component to the storyboard. Change the title of the button to Reset.
  • Add a new Action function named reset to the ViewController file.
  • Add a new function that we will delegate from both the increment and reset functions.

private func updateLabel(value: Int) {
    NSLog("Clicked %d times", value)
    text.text = "\(value)"
  }


  • Modify the increment function to use the updateLabel function.

counter += 1
updateLabel(value: counter)


  • Implement the reset function using the updateLabel function.

counter = 0
updateLabel(value: counter)


  • Build and run the app.

ViewController.swift

import UIKit

class ViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  var counter = 0
  @IBOutlet weak var text: UITextField!

  @IBAction func increment() {
    counter += 1
    updateLabel(value: counter)
  }
  
  @IBAction func reset() {
    counter = 0
    updateLabel(value: counter)
  }
  
  private func updateLabel(value: Int) {
    NSLog("Clicked %d times", value)
    text.text = "\(value)"
  }
}

Unit Testing

Unit testing is the process of testing various parts (functional and/or UI) of the application automatically as part of the development process. Xcode projects present the option of adding functional (code) and UI testing (application) when you create a project.

We will record a test run of our demo application, and then add a few assertions to ensure that the application behaves as expected.

  • Open the DemoUITests.swift file that Xcode automatically created for us in the editor.
  • Place the mouse cursor in the testExample function.
  • Click the “Record UI Test” (red button in the bottom left pane). This will launch the application in the simulator and record the actions we perform on the app.
  • Click the Increment button a few times, followed by the Reset button. Repeat a few more clicks of the Increment button followed by the Reset button.
  • Stop the test recording.
  • Add lines similar to the following between the tap function calls generated by the recording.

XCTAssertEqual("1", textField.value as! String)

  • Run the test suite.

import XCTest

class DemoUITests: XCTestCase {
        
    override func setUp() {
        super.setUp()
        XCUIApplication().launch()
    }
    
    override func tearDown() {
        super.tearDown()
    }
    
    func testExample() {
      let app = XCUIApplication()
      let textField = app.textFields["label"]
      
      let incrementButton = app.buttons["Increment"]
      
      incrementButton.tap()
      XCTAssertEqual("1", textField.value as! String)
      incrementButton.tap()
      XCTAssertEqual("2", textField.value as! String)
      incrementButton.tap()
      XCTAssertEqual("3", textField.value as! String)
      incrementButton.tap()
      XCTAssertEqual("4", textField.value as! String)
      
      let resetButton = app.buttons["Reset"]
      resetButton.tap()
      XCTAssertEqual("0", textField.value as! String)
      incrementButton.tap()
      XCTAssertEqual("1", textField.value as! String)
      incrementButton.tap()
      XCTAssertEqual("2", textField.value as! String)
      resetButton.tap()
      XCTAssertEqual("0", textField.value as! String)  
    }
}