SwiftMobile Application Development in iOS
School of EECS
Washington State University
Instructor: Larry Holder
Mobile Application Development in iOS 1
Why Swift
• Recommended for all iOS, macOS, watchOS, and tvOS
app development
• Designed by Apple, but now open source
• Available for Windows and Linux too
• Faster than Python, and C++ in some cases
– Can directly call C/C++ code
• Swift vs. Python, C++, Java, Go, …
Mobile Application Development in iOS 2
Good Tutorials• The Swift Programming Language (Swift 4)
– developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language
– The Swift Tour
– Includes Playground for all code
• Ray Wenderlich
– http://raywenderlich.com/category/swift
Mobile Application Development in iOS 4
Caveat
• Assume proficiency in some object-oriented
language (e.g., C++, Java, Python)
Mobile Application Development in iOS 5
Constants, Variables & Types
• Constants (let) vs. variables (var)
• Types (convention: first letter capitalized)
– Basic types: Bool, Int, Float, Double, String
– Collection types: Array, Set, Dictionary
– Tuples
Mobile Application Development in iOS 6
var shoppingList = ["coffee": 3, "candy": 4]for (item, amount) in shoppingList {
print("\(item): \(amount)")}
Optionals
• Optional variable can be nil or hold a value
• Optional binding
Mobile Application Development in iOS 7
let possibleStr: String? = "Hello" // optional typeprint(possibleStr) // outputs "Optional("Hello")”, warninglet forcedStr: String = possibleStr! // unwrappingprint(forcedStr) // outputs "Hello"let assumedStr: String! = "Hello" // implicitly unwrappedlet implicitStr: String = assumedStr // no need for !
if let tempStr = possibleStr {print(tempStr)
}
Range Operators
• Range operators (a…b, a..<b)
Mobile Application Development in iOS 8
let count = 5for index in 1...count {
print("\(index)") // 1 2 3 4 5}
for index in 0..<count {print("\(index)") // 0 1 2 3 4
}
Functions
Mobile Application Development in iOS 9
func fahrenheitToCelsius (temp: Float) -> Float {let tempC = (temp - 32.0) * 5.0 / 9.0return tempC
}
func printCelsius (temp tempF: Float) {let tempC = fahrenheitToCelsius(temp: tempF)print("\(tempF) F = \(tempC) C")
}
func printF2CTable (_ low: Int = 0, _ high: Int = 100) {for temp in low...high {
printCelsius(temp: Float(temp))}
}printF2CTable()printF2CTable(70)printF2CTable(70,80)
Function Types
Mobile Application Development in iOS 10
func addTwoInts (_ a: Int, _ b: Int) -> Int {return a + b
}
var mathFunction: (Int, Int) -> Int = addTwoInts
print("Result: \(mathFunction(2, 3))") // prints “Result: 5”
func printMathResult (_ mathFunction: (Int, Int) -> Int,_ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")}
printMathResult(addTwoInts, 3, 5) // prints “Result: 8”
Closures
• Self-contained block of code
• Can capture references to variables in context
• General form:
Mobile Application Development in iOS 11
{ (parameters) -> return-type instatements
}
Closures (cont.)
Mobile Application Development in iOS 12
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ s1: String, _ s2: String) -> Bool {return s1 > s2
}
var reversedNames = names.sorted (by: backward)
reversedNames = names.sorted (by: { (s1: String, s2: String) -> Bool inreturn s1 > s2
})
Closures: Capturing Values
Mobile Application Development in iOS 13
func makeIncrementer(forIncrement amount: Int) -> () -> Int {var runningTotal = 0func incrementer() -> Int {
runningTotal += amountreturn runningTotal
}return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen() // returns a value of 10incrementByTen() // returns a value of 20incrementByTen() // returns a value of 30
Escaping Closures• Closure passed to function, but called after function returns
Mobile Application Development in iOS 14
var completionHandlers: [() -> Void] = []
func addCompletionHandler (handler: @escaping () -> Void) {completionHandlers.append(handler)
}
func printHello() {print("Hello")
}
addCompletionHandler(handler: printHello)for handler in completionHandlers {
handler()}
Enumerations
Mobile Application Development in iOS 15
enum Direction {case up // does not imply .up = 0case leftcase downcase right
}
var playerDirection = Direction.rightplayerDirection = .up // type inference
func turnLeft (direction: Direction) -> Direction {var newDirection: Directionswitch direction {
case .up: newDirection = .left // no breakcase .left: newDirection = .downcase .down: newDirection = .rightcase .right: newDirection = .up
}return newDirection
}
Enumerations (cont.)
• Raw values
Mobile Application Development in iOS 16
func facingLeftOrRight (direction: Direction) -> Bool {switch direction {
case .left, .right: return truedefault: return false
}}
enum Direction: Int {case up = 0, left, down, right // now they’re Int’s
}Direction.left.rawValue // equals 1
enum Direction: String {case up, left, down, right // now they’re String’s
}Direction.left.rawValue // equals “left”
Classes
Mobile Application Development in iOS 17
class Player {var direction: Directionvar speed: Floatvar inventory: [String]? // initialized to nil
// init required to set uninitialized variablesinit (speed: Float, direction: Direction) {
self.speed = speedself.direction = direction
}
func energize() {speed += 1.0
}}
var player = Player(speed: 1.0, direction: .right)
Classes (cont.)
Mobile Application Development in iOS 18
class FlyingPlayer : Player {var altitude: Float
init (speed: Float, direction: Direction, altitude: Float) {self.altitude = altitudesuper.init (speed: speed, direction: direction)
}
override func energize() {super.energize()altitude += 1.0
}}
var flyingPlayer = FlyingPlayer(speed: 1.0, direction: .right, altitude: 1.0)
Must initialize all non-optional child properties before initializing parent.
Class vs. Struct
• Classes passed by reference
• Structs passed by value
Mobile Application Development in iOS 19
class Foo1 {var x : Int = 1
}func changeX (foo : Foo1) {
foo.x = 2}
var foo1 = Foo1()changeX(foo: foo1)foo1.x // equals 2
struct Foo2 {var x : Int = 1
}
func changeX (foo: Foo2) {foo.x = 2 // errorvar tmpFoo: Foo2 = footmpFoo.x = 2
}
var foo2 = Foo2()changeX(foo: foo2)foo2.x // equals 1
Optional Chaining
Mobile Application Development in iOS 20
var myPlayer = Player(speed: 1.0, direction: .right)
let firstItem = myPlayer.inventory.first // errorlet firstItem = myPlayer.inventory!.first// errorlet firstItem = myPlayer.inventory?.first// nil (OC)myPlayer.inventory?.append("potion") // nil (OC: no effect)type(of: firstItem) // Optional<String>
if let item = myPlayer.inventory?.first {print("item = \(item)") // nothing printed (OC)
}
myPlayer.inventory = [] // array initializedmyPlayer.inventory?.append("potion") // “potion” addedlet item = myPlayer.inventory?.first // “potion”
if let item = myPlayer.inventory?.first {print("item = \(item)") // “item = potion”
}
Error Handling
• Do-try-throw-catch error handling
Mobile Application Development in iOS 21
enum myError : Error {case goodcase badcase fatal
}
func throwsError () throws {throw myError.fatal
}
func testError () {do {
try throwsError()print("no error")
} catch myError.fatal {print("fatal")
} catch {print("good or bad")
}}
Error Handling• try?: returns nil if error thrown
• try!: assumes no error thrown (or exec error)
• guard <condition> else {throw or return}
– Preferred to: if not <condition> {throw or return}
Mobile Application Development in iOS 22
if let result = try? throwsError() {print("no error: result = \(result)")
}let forcedResult = try! throwsError()guard (amount > 0) else {
throw myError.bad}
Type Casting• Regular type casting
• Downcasting (as?, as!)
Mobile Application Development in iOS 23
let x = 10 let xstr = String(x) // “10”, xstr of type Stringlet xstr2 = "\(x)" // “10” let ystr = "100"let y = Int(ystr) // 100, y of type Optional<Int>var arrayOfAnything: [Any]var arrayOfAnyClassInstances: [AnyObject]
var playerArray = [Player]()playerArray.append(flyingPlayer)playerArray.append(player)var fp : FlyingPlayer!fp = playerArray[0] as? FlyingPlayer // fp = flyingPlayerfp = playerArray[1] as? FlyingPlayer // fp = nilfp = playerArray[1] as! FlyingPlayer // error
Protocols
• Required properties and methods
• Adopted by class, struct or enum type
• Said to “conform” to protocol
Mobile Application Development in iOS 24
protocol MyFunProtocol {func isFun() -> Bool
}
class MyFunClass: MyFunProtocol {func isFun() -> Bool {
return true}
}
Delegation• Use protocols so class can delegate to others
Mobile Application Development in iOS 25
protocol MyFunDelegate {func isFun() -> Bool
}
class MyFunDelegateClass: MyFunDelegate {func isFun() -> Bool {
return true}
}
class MyFunClass {var delegate: MyFunDelegate?
func fun() -> Bool {return delegate!.isFun()
}}
var myFunClass = MyFunClass()var myFunClassDelegate = MyFunDelegateClass()myFunClass.delegate = myFunClassDelegatemyFunClass.fun() // returns true