11 - iOS Swift
Swift
Swift Playgrounds
- iPad app, 3D video game-like interface, moving closer to full editor
- Xcode
- Web based - http://online.swiftplayground.run
Swift variables
Constants
| let school: String = "TalTech IT College"
let founded: Int = 2000
let isAwesome: Bool = true
|
Type inference
| let school = "TalTech IT College"
let founded = 2000
let isAwesome = true
|
Variables
Strings
Concatenation
| let school = "TalTech IT College"
let message = "Hello, " + school + "!"
|
Interpolation
| let school = "TalTech IT College"
let message = "Hello, \(school)!"
|
Full unicode support
| let õäöüžšج信息技术 = "信息技术õäüöžšب ت جث"
|
Characters
| let õäöüžšج信息技术 = "信息技术õäüöžšب ت جث"
print("\(õäöüžšج信息技术) is \(õäöüžšج信息技术.count) chars long")
\\ 16
|
Iteration
| let õäöüžšج信息技术 = "信息技术õäüöžšب ت جث"
for character in õäöüžšج信息技术 {
print(character)
}
|
Collections
Array and Dictionary
| let names: [String] = ["Jüri", "Mari", "Kalle"]
let ages = ["Kalle": 17, "Malle": 18]
|
Loops
While and Repeat-While
| var name = "test"
var i = 0
while i < name.characters.count {
print("At pos \(i) is \(name[name.index(name.startIndex, offsetBy: i)])")
i += 1
}
|
| i = 0
repeat {
print("At pos \(i) is \(name[name.index(name.startIndex, offsetBy: i)])")
i += 1
} while i < name.characters.count
|
For-In Loop – closed ranges
| for number in 1...5 {
print(number)
}
|
Half closed ranges
| let numbers = [7, 6, 42, 3, 9, 1]
let maxCount = 4
for index in 0..<maxCount {
print(numbers[index])
}
|
For-In Loop – Array & Dictionary
| let ages = ["Kalle": 17, "Malle": 18]
for (name, age) in ages {
print("\(name) - \(age)")
}
|
Array
Modifying
| var numbers = [7, 6, 42, 3, 9, 1]
numbers.append(5)
numbers[1] = 8
|
Append multiple
| numbers.append(contentsOf: [4, 13, -5])
|
Remove elements (0 based index) and insert new ones
Optionals
Maybe value is not there?
| let ages = ["Kalle": 17, "Malle": 18]
let possibleAge = ages["Malle"]
print("\(possibleAge)")
let possibleAge: Int? = ages["Malle"]
|

Checking
| if possibleAge == nil {
print("Age not found.")
}
|
if let
| let ages = ["Kalle": 17, "Malle": 18]
if let age = ages["Kalle"] {
print("Kalle's age is \(age)")
}
|
switch
| let age = 90
switch age {
case 1:
print("First year done")
case 13...19:
print("Teenager is hard period!")
case let decade where decade % 10 == 0:
print("Congrats on \(decade)*10 years")
default:
print("regular birthday")
|
Switch over multiple values
| let userName = "admin"
let passwordIsValid = true
switch (userName, passwordIsValid) {
case ("admin", true):
print("admin you are")
case ("guest", _):
print("guests not allowed")
case (_, let isValid):
print(isValid ? "admin area granted" : "DENIED")
}
|
Functions
| func sendMessage() {
let message = "Hello!"
print(message)
}
sendMessage()
|
Parameters
| func sendMessage(shouting: Bool) {
var message = "Hello!"
message = shouting ? message.uppercased() : message
print(message)
}
sendMessage(shouting: true)
|
Multiple parameters (argument, label)
| func sendMessage(recipient: String, shouting: Bool) {
let message = "Hello \(recipient)!"
print(shouting ? message.uppercased() : message)
}
sendMessage(recipient: "Andres", shouting: true)
|
Better to read in usage, bad in function code
| func sendMessage(to: String, shouting: Bool) {
let message = "Hello \(to)!"
print(shouting ? message.uppercased() : message)
}
sendMessage(to: "Andres", shouting: true)
|
Parameters - argument label and a parameter name
| func sendMessage(to recipient: String, shouting: Bool) {
let message = "Tere \(recipient)!"
print(shouting ? message.uppercased() : message)
}
sendMessage(to: "Andres", shouting: true)
|
Parameters – using underscore – no label
| func sendMessage(message: String, to recipient: String, shouting: Bool) {
let message = "\(message), \(recipient)!"
print(shouting ? message.uppercased() : message)
}
sendMessage(message: "Hello", to: "Andres", shouting: true)
|
| func sendMessage(_ message: String, to recipient: String, shouting: Bool) {
let message = "\(message), \(recipient)!"
print(shouting ? message.uppercased() : message)
}
sendMessage("Hello", to: "Andres", shouting: true)
|
Return values
| func firstString(havingPrefix prefix: String, in strings: [String]) -> String? {
for string in strings {
if string.hasPrefix(prefix){
return string
}
}
return nil
}
print("Result \(firstString(havingPrefix: "And", in: ["Jüri", "Andres"]))")
|
Function type
Function type
(parameter types) -> return type
| func sendMessage() {}
() -> Void
func firstStr(havingPrefix prefix: String, in strings: [String]) -> String? {}
(String, [String]) -> String?
|
Functions as parameters
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | func filterInts(_ numbers: [Int], _ includeNumber: (Int) -> Bool) -> [Int] {
var result: [Int] = []
for number in numbers {
if includeNumber(number) {
result.append(number)
}
}
return result
}
let numbers = [4, 17, 34, 41]
func divisibleByTwo(_ number: Int) -> Bool {
return number % 2 == 0
}
let evenNumbers = filterInts(numbers, divisibleByTwo)
print(evenNumbers)
|
Closure expression - Inline function definitions (not named functions)
| func divisibleByTwo(_ number: Int) -> Bool {
return number % 2 == 0
}
let evenNumbers =
filterInts(numbers, { (number: Int) -> Bool in return number % 2 == 0})
|
Closures - definition
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | func filterInts(_ numbers: [Int], _ includeNumber: (Int) -> Bool) -> [Int] {……}
let numbers = [4, 17, 34, 41]
print( filterInts(numbers, { (number: Int) -> Bool in return number % 2 == 0}) )
// can be inferred from filterIntents declaration
print( filterInts(numbers, { number in return number % 2 == 0}) )
// if its single liner, no need for return keyword
print( filterInts(numbers, { number in number % 2 == 0}) )
// implicit arguments, no need for in keyword
print( filterInts(numbers, {$0 % 2 == 0}) )
// if closure is last argument, you can write as trailing closure
print( filterInts(numbers) {$0 % 2 == 0} )
|
Generics
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | let numbers = [4, 17, 34, 41]
let names = ["Andres", "kala"]
func filter<TElement>(_ source: [TElement],
_ includeElement: (TElement) -> Bool) -> [TElement] {
var result: [TElement] = []
for elem in source {
if includeElement(elem) {
result.append(elem)
}
}
return result
}
let evenNumbers = filter(numbers) { $0 % 2 == 0 }
let shortNames = filter(names) { name in name.count < 5 }
|
Map, Filter
Closures and generics are widely used in Swift libraries
1
2
3
4
5
6
7
8
9
10
11
12 | let names = ["Lily", "Santiago", "Aadya", "Jack", "Anna", "Andrés"]
let shortNames = names.filter({ name in name.count < 5 })
let shortNames1 = names.filter() { name in name.count < 5 }
let shortNames2 = names.filter { name in name.count < 5 }
print(shortNames)
let capitalizedShortNames = shortNames.map { name in name.uppercased() }
print(capitalizedShortNames)
|