1/94

Hands-On Crash-Course on iOS Development

2/94

Agenda

3/94

iOS Overview - Facts

4/94

iOS Architecture

center 70%

5/94

Application Runtime Environment

6/94

Application Runtime Environment

7/94

Application Structure

Each iOS app is composed of at least the following parts:

  • Datamodel (app dependent)
    • Class: e.g. UIDocument
  • Controller
    • Classes: UIApplication, UIViewController
    • Protocol: UIApplicationDelegate
  • View
    • Classes: UIWindow, UIView based classes

center 80% Source: Apple

8/94

Application Life Cycle

  • Different application states
State Description
Not running The application has not been launched or was running but was terminated by the system
Inactive The application is running in the foreground but is currently not receiving events
Active The application is running in the foreground and is receiving events.
Background The application is in the background and executing code (only iOS > v.4)
Suspended The application is in the background but is not executing code (only iOS > v.4)

center 70% Source: Apple

9/94

Development Tools

  • Xcode: IDE including Debugger
    • IDE for Mac OS X and iOS
    • Sourcecode editor
    • Debugging in simulator and remote on device supported
    • Compiler: Apple LLVM Compiler
    • Current version: 10.1

center 80%

10/94

Development Tools

  • Simulator (not an emulator)
  • Simulating the iOS devices using iOS libraries on Mac OS X
  • Uses Intel code, simulates GPS, multitouch (pressing alt), shaking the device and orientation changes
  • Logs error messages to console

center 40%

11/94

Development Tools

center 60%

12/94

Development Tools

center 60%

13/94

Development Tools

center 60%

Source: Apple

14/94

Simple iOS App Example & Assignment

15/94

Storyboards

center

16/94

UI Components

17/94

Storyboards Assignment

18/94

Swift

var str = "Hello World"
print(str)
19/94

Swift Language Goals

20/94

Whats New?

21/94

Swift Language Fundamentals

22/94

Variables

var myvariable = 0
var myvariable : Int = 0
23/94

Variables

var name = "Name" // Type is inferred as String
        
var age = 38 // Type is inferred as Int
        
var weight = 90.5 // Type is inferred as Double
        
var myvariable : Int // Type annotation defining type Int
        
var myName : String = "Ansgar"

24/94

Constants

let myconstant = 10
var myvariable = 0, yourvar = 1, anothervar = 3
25/94

Optionals

var rabbit : String? //declares optional String
... //rabbit = "running"
if(rabbit != nil){
    print("Rabbit is \(rabbit!)") //unwraps Optional
}
else {
    print("Rabbit is nil")
}
26/94

Enumerations

enum GraphicalObjects {
    case Circle
    case Rectangle
    case Polygon
}

var go = GraphicalObjects.Circle

if go == GraphicalObjects.Circle {
    print("is a Circle")
}
else if go == .Rectangle {
    print("is a Rectangle")
}
else {
    print("is a Polygon")
}
27/94

Basic Data Types

28/94

Int

var smallInt : UInt8 = 5
var largertInt : Int16 = 10
var evenLargerInt : Int32 = 100
var biggestInt : UInt64 = 1000
UInt8.min //0
UInt8.max //255
Int16.min // -32768
Int16.max // 32768
29/94

Float, Double

var mySmallFloat : Float = 2.34352
var myBigFloat : Double = 3.42323
let pi = 3 + 0.14159
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1
30/94

Boolean

let hdmIsGreat = true
let swiftIsBoring = false
let i = 1
if i {
    //will not compile and report an error
}
let i = 1
if i==1 {
    //this works
}
31/94

Range

A Range or CountableRange (since Swift 3.0) is a type in Swift that defines a number of elements that can be iterated over, e.g. a number of integer values or String.Index values The Range can be created using the range operator: ClosedRange operator: ... Range operator: ..<

let myFromZeroTo5Range = 0...5 //CountableClosedRange(0...5)
let myFromZeroToSmallerSixRange = 0..<6 //CountableRange(0..<6))

Since Swift 3.0 ClosedRange (...) and Range (..<) are two different types which can not be converted into each other.

32/94

Strings & Characters

Swift Strings and Characters are value types, Unicode compliant and easy to use

let emptyImmutableString = ""
var emptyMutableString = ""
var emptyString = String()
let sparklingHeart = "\u{1F496}" 

String values can be constructed by passing an array of Characters

let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)

Concatenation of Strings and Characters is simple

let string1 = "Hello "
let string2 = "HdM"
let char1: Character = "!"

var concatenatedString = string1 + string2 //"Hello HdM"
concatenatedString.append(char1) // "Hello HdM!"
33/94

Strings & Characters

String interpolation allows to create a new String from multiple variables or literals

let multiplier = 3
let message = "\(multiplier) times 2 is \(multiplier*2)" 
//„3 times 2 is 6“

Expressions in the parentheses cannot contain double quotes, backslashes, a carriage return or line feed You can call functions within the parentheses

func getHint() -> String {
    return "special hint"
}
let newmessage = "New hint: \(getHint())" //„New hint: special hint“
34/94

Strings & Characters

The property „characters“ allows you to iterate over all characters in a String

for letter in string.characters {
    
    print("\(letter)")
    
}

Use count() to count Chars

string.characters.count // 19

Use can create a range to access Characters of a part of a String

let range = string.index(string.startIndex, offsetBy: 5)..<string.index(before: string.endIndex)

for mindex in string.characters.indices[range] {
    print("\(string[mindex])",terminator: "")
}
35/94

Strings & Characters

To modify strings, you can use insert(), remove() and removeSubrange()

var myString = "Hello HdM"

var idx = myString.index(myString.endIndex, offsetBy: -2) //7

myString.remove(at: idx) // „Hello HM“

let r = myString.index(myString.startIndex, offsetBy: 5)..<myString.endIndex

myString.removeSubrange(r) // „Hello“

myString.insert("!", at: myString.endIndex) //"Hello HM!"
36/94

Strings & Characters

String and Character equality is checked using the „equal to“ operator (==) Strings are equal if they have the same linguistic meaning and appearance, even if they are composed from different Unicode scalars

let eAcuteQuestion = "Voulez-vous un caf\u{E9}?"
let combinedEAcuteQuestion = "Voulez-vous un caf\u{65}\u{301}?"
if eAcuteQuestion == combinedEAcuteQuestion {
    print("\(eAcuteQuestion) and \(combinedEAcuteQuestion) are considered equal")
}
// "Voulez-vous un café? and Voulez-vous un café? are considered equal"
37/94

Strings & Characters

You can check the prefix or suffix of a String using hasPrefix() and hasSuffix()


let stringArray = ["1st String of 2","2nd String of 2"]
    
    for string in stringArray {
    if string.hasPrefix("1st"){
    print("String starting with 1st: \(string)")
    }
    if string.hasSuffix("2") {
    print("String ending with 2: \(string)")
    }
}

38/94

Arrays

Arrays are next to sets and dictionaries the mostly used collections in swift To create a mutable array, assign it to a variable (e.g. var myArray)

var shoppingList = [String]()

Initialize directly by writing:

var shoppingList = ["Apples","Pears","Bread","Milk"]
39/94

Arrays

Appending items to an Array

shoppingList.append("Soap")
//or
shoppingList += ["Juice"]

Adding Arrays and creating new ones

var familyList = shoppingList + ["Cornflakes","Ice Cream"]

Removing items from an Array

shoppingList.remove(at: 2)
shoppingList.removeLast()
shoppingList.removeAll(keepingCapacity: true)
40/94

Arrays

Check if an Array is empty

if shoppingList.isEmpty {
    ...
}

Retrieve a certain item or a part of the Array

shoppingList[5] //-> "Cornflakes"
shoppingList[1...3] //["Pears", "Bread", "Milk"]
41/94

Tuples

Tuples group multiple values into a single compound value

let httpStatus = (404, "Not Found")

Each single value is accessible by a number, e.g.:

httpStatus.0 // 404
httpStatus.1 // "Not Found"

Tuples can be decomposed into their separate values

let (statusCode, description) = httpStatus
print("Statuscode: \(statusCode) means: \(description)")

You can name the elements in a tuple and access them using the names

let newHttpStatus = (code: 200, description: "OK")
print("code: \(newHttpStatus.code)")
print("description: \(newHttpStatus.description)")
42/94

Control Flow

43/94

For-In-Loop

Iterating over an Array

var familyList = ["Milk", "Bread","Soap","Juice"]
for item in familyList {
    print(item)
}

Iterating with index and value

for (index,value) in familyList.enumerated() {
    print("item nbr. \(index + 1) is: \(value)")
}
44/94

For-Loop

Since Swift 3.0 for-loops look like this:

for index in 0 ..< 3 {
    print("index is \(index)")
}

C-style loops are not supported anymore

45/94

While

Use the while loop to iterate while a condition is true

var shoppingList = ["Apples","Pears","Bread","Milk"]
while !shoppingList.isEmpty {
    print("remove one item from list")
    shoppingList.removeLast()
}

Use do-while to test the condition after executing the statements

shoppingList = ["Apples","Pears","Bread","Milk"]
repeat {
    shoppingList.removeLast()
} while !shoppingList.isEmpty
46/94

If

Test a condition using if The else-if and final else clause is optional

var temperatureInFahrenheit = 90
if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
} else {
    print("It's not that cold. Wear a t-shirt.")
}
// prints "It's really warm. Don't forget to wear sunscreen."
47/94

Switch

let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
    print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
    print("\(someCharacter) is a consonant")
default:
    print("\(someCharacter) is not a vowel or a consonant")
}
48/94

Switch With Tuple

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    print("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    print("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    print("(\(x), \(y)) is just some arbitrary point")
}
// prints "(1, -1) is on the line x == -y"
49/94

Swift Assignment

50/94

Functions & Closures

func greet(name: String, day: String) -> String {
    return "Hello \(name), today is \(day)."
}
greet(name: "Bob", day: "Tuesday")
51/94

Functions & Closures

func greet(name: String, day d: String) -> String {
    return "Hello \(name), today is \(d)."
}
greet(name: “Bob", day: "Tuesday")
52/94

Functions & Closures

It is possible to return multiple values from a function using Tuples

func getGasPrices() -> (Double, Double, Double) {
    return (3.59, 3.69, 3.79)
}
getGasPrices()

Functions can take a variable number of arguments

func sumOf(numbers: Int...) -> Int {
    var sum = 0
   	for number in numbers {
        sum += number
   	}
    return sum
}
sumOf()
sumOf(numbers: 42, 597, 12)
53/94

Functions & Closures

func returnFifteen() -> Int {
	var y = 10
    func add() {
        y += 5
    }
    add()
    return y
}
returnFifteen()
54/94

Functions & Closures

func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)
55/94

Functions & Closures

func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}

func lessThanTen(number: Int) -> Bool {
    return number < 10
}

var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers,condition: lessThanTen)
56/94

Functions & Closures

var numbers = [20, 19, 7, 12]
numbers.map({
    (number: Int) -> Int in
    let result = 3 * number
    return result
})
57/94

Classes

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}
58/94

Classes

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}
let myShape = Shape()
myShape.numberOfSides = 10
myShape.simpleDescription()
59/94

Classes

class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

let s = NamedShape(name: "MyShape")
60/94

Assert

let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// this causes the assertion to trigger, because age is not >= 0
61/94

Exception Handling Try / Catch & Guard

class FatherChristmas {
    
    enum DeliveryError : Error {
        case NoPresentsRemaining
    }
    
    var numberOfPresents = 0
    
    func deliverPresents() throws {
        guard numberOfPresents > 0 else {
            throw DeliveryError.NoPresentsRemaining
        }
        print("Presents delivered")
    }
    func itIsChristmasEve(){
        do {
            try deliverPresents()
        } catch DeliveryError.NoPresentsRemaining{
            print("Could not deliver presents!")
        } catch {
            print("Unknown error")
        }
    }
    
}
let fatherChristmas = FatherChristmas()
fatherChristmas.itIsChristmasEve()
62/94

Protocol Extensions

//this protocol defines the "description" method used by many classes
extension CustomStringConvertible {
    var shoutyDescription: String {
        return "\(self.description.uppercased())!!!"
    }
}

let greetings = ["Hello", "Hi", "Yo yo yo"]

print("\(greetings.description)")
    
    // prints "["HELLO", "HI", "YO YO YO“]!!!\n"
    
print("\(greetings.shoutyDescription)")
63/94

Swift is OpenSource

64/94

Swift References

65/94

UIKit

66/94

UIView & UIWindow

67/94

UIView & UIWindow

center

Source

68/94

Core Animation

  • Uses „layer“ objects that render the content of your view into a bitmap
  • Layers can be easily animated using full power of the graphics hardware
  • Animations modify the 
properties of the layer over time
  • You can use it to change the 
opacity, the position and
the size and orientation of the layer on screen

69/94

The App Delegate

70/94

App Delegate Methods

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }
71/94

UIViewController

import UIKit // UIViewController is part of the UIKit Framework

class ViewController: UIViewController {

    @IBOutlet weak var myLabel: UILabel!
    
    override func viewDidLoad() { // called when the view becomes visible
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() { // called when the system is running low on memory
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    @IBAction func buttonTouched(sender: UIButton) { // custom action method
        
        myLabel.text = "Hello Swift"
        
        
    }
}

72/94

Event Handling

center

Source

73/94

UIResponder

center Source

74/94

First Responder

75/94

Responder Chain

center 60% Source

76/94

Multi-Touch Event Handling

   override func touchesBegan(_: Set<UITouch>, with: UIEvent?){
        print("touches began")
    }
    
    override func touchesEnded(_: Set<UITouch>, with: UIEvent?){
        print("touches ended")
    }
    
    override func touchesMoved(_: Set<UITouch>, with: UIEvent?){
        print("touches moved")
    }
    override func touchesCancelled(_: Set<UITouch>, with: UIEvent?){
        print("touches cancelled")
    }
77/94

UITextField

  @IBAction func returnPressed(sender: AnyObject) {
        myTextField.resignFirstResponder()
   }

78/94

View Controller Assignment

79/94

Protocols in Swift

80/94

Protocols in Swift

protocol SomeProtocol {
    // protocol definition goes here
}

class SomeClass: SomeSuperClass, FirstProtocol, SomeProtocol {
    // class definition goes here
}
81/94

Protocols in Swift

protocol SomeProtocol {

    // a settable Property must be implemented using 
    // var in the implementing class
    var mustBeSettable: Int { get set } 

    // a only gettable Property should be implented using let
    var doesNotNeedToBeSettable: Int { get }

}
82/94

Protocols in Swift

protocol RandomNumberGenerator {

    func random() -> Double

}
83/94

Properties

center 70%

84/94

Properties

center 70%

85/94

Class & Protocol Assignment

86/94

UITableViewController

  • UIKit class to create lists
    • Similar to ListActivity on Android
  • Contains a UITableView to show items in a list
    • Similar to the ListView on Android
  • Makes use of the Delegate pattern by 
implementing, e.g. following Protocols
    • UITableViewDelegate
    • UITableViewDataSource
      • Similiar to the ListAdapter on Android
50%
87/94

UITableViewDelegate

88/94

UITableViewDelegate

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("Selected row \(indexPath.item)")
    }

89/94

UITableViewDataSource

90/94

UITableViewDataSource


// Override to define the number of sections for the table
override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

// Override to define the number of rows in each section 
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return shoppingList.count
    }

// Override to define the cell for a given row
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)

        // Configure the cell...
        
        cell.textLabel?.text = shoppingList[indexPath.item]

        return cell
    }
91/94

UITableView

  • The UITableView defines the visible list that is controlled by the UITableViewController
  • Inherits from UIScrollView
  • Can have one of two styles
    • UITableViewStylePlain
    • UITableViewStyleGrouped
  • Each row in the UITableView is defined by a UITableViewCell
50%
92/94

UITableViewCell

  • The UITableViewCell defines the content of the cells that appear in a UITableView
  • Inherits from UIView
  • Has a predefined textLabel, a detailTextLabel and an imageView Property
  • Has a „Reuse Identifier“ to save resources when rendering
  • Supports different Cell-Styles
    • Basic
    • Right Detail
    • Left Detail
    • Subtitle
50%
93/94

TableView Assignment

94/94

Practical Hands-On