Skip to content

Swift Xcode

Mingtao edited this page Aug 15, 2019 · 31 revisions

Xcode shortcut keys

Cmd 0: hide/show left panel

Cmd 1: show project navigator

Cmd Option 0: hide/show right panel

Option left-click a file: Open file side by side

Cmd Shift F: Search within file / file name

Cmd Shift O: Open file

Option left-click a variable: Check its type

Swift code

String

Character at index of a string

let greeting = "Hello world!"
let firstChar = greeting[greeting.startIndex] // 'H'
let secondCharIndex = greeting.index(greeting.startIndex, offsetBy: 1)
let secondChar = greeting[secondCharIndex] //'e'
let lastCharIndex = greeting.index(before: greeting.endIndex)
let lastChar = greeting[lastCharIndex] //'!'
let secondLastCharIndex = greeting.index(greeting.endIndex, offsetBy: -2)
let secondLastChar = greeting[secondLastCharIndex] //'d'

Insert and Remove

var welcome = "hello"
welcome.insert("!", at: welcome.endIndex)
// welcome now equals "hello!"
welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there!"
welcome.remove(at: welcome.index(before: welcome.endIndex))
// welcome now equals "hello there"
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
// welcome now equals "hello"

Substring

let greeting2 = "Hello,world!"
let index = greeting2.firstIndex(of: ",") ?? greeting2.endIndex
let excludeIndexSubstring = greeting2[..<index] //"Hello" of type String.SubSequence
let includeIndexSubstring = greeting2[...index] //"Hello," of type String.SubSequence
let newString = String(excludeIndexSubstring) //"Hello" of type String

Array / List

var someInts = [Int]()
someInts.append(3)
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]
var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
// anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]
var shoppingList = ["Eggs", "Milk"]
shoppingList += ["Baking Powder"]
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
shoppingList.insert("Maple Syrup", at: 0)
let mapleSyrup = shoppingList.remove(at: 0)
let apples = shoppingList.removeLast()
for item in shoppingList {
    print(item)
}
for (index, value) in shoppingList.enumerated() {
    print("Item \(index + 1): \(value)")
}

Set

A type must be hashable in order to be stored in a set

var letters = Set<Character>()
let count = letters.count
let isEmpty = letters.isEmpty
letters.insert("a")
letters = [] // letters is now an empty set, but is still of type Set<Character>
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
var favoriteGenres2: Set = ["Rock", "Classical", "Hip hop"] //Simpler than above line
let removedGenre = favoriteGenres.remove("Rock")
let contains = favoriteGenres.contains("Funk")
for genre in favoriteGenres.sorted() {
    print("\(genre)")
}
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
oddDigits.union(evenDigits).sorted() // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted() // []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted() // [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted() // [1, 2, 9]
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals) // true
farmAnimals.isSuperset(of: houseAnimals) // true
farmAnimals.isDisjoint(with: cityAnimals) // true. To determine whether two sets have no values in common.

Dictionary

A dictionary Key type must conform to the Hashable protocol, like a set’s value type.

var namesOfIntegers = [Int: String]()
namesOfIntegers[16] = "sixteen"
namesOfIntegers = [:] // namesOfIntegers is once again an empty dictionary of type [Int: String]
let count = namesOfIntegers.count
let isEmpty = namesOfIntegers.isEmpty
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
var airports2 = ["YYZ": "Toronto Pearson", "DUB": "Dublin"] //Simpler format than above line
airports["LHR"] = "London"
let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") //oldValue is of type string?
airports["APL"] = nil //Remove a key-value pair
let removedValue = airports.removeValue(forKey: "DUB") //Another way to remove a key-value pair

for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)")
}
for airportCode in airports.keys {
    print("Airport code: \(airportCode)")
}
for airportName in airports.values {
    print("Airport name: \(airportName)")
}
let airportCodes = [String](airports.keys) // airportCodes is ["LHR", "YYZ"]
let airportNames = [String](airports.values) // airportNames is ["London Heathrow", "Toronto Pearson"]

Control flow

for loop

// Open range (i.e. not include 60)
let minuteInterval = 5
let minutes = 60
for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {
    print (tickMark)// render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)
}

//Close range (i.e. include 12)
let hours = 12
let hourInterval = 3
for tickMark in stride(from: 3, through: hours, by: hourInterval) {
    print (tickMark)
}

while loop

var a = 0
var b = 5
while a < b {
    print (a)
    if a == 3 {
        break
    }
    a += 1
}

repeat while loop

a = 0
repeat {
    print (a)
    a += 1
}while a < b

switch

switch statements in Swift do not fall through the bottom of each case and into the next one by default.

let approximateCount = 62
let countedThings = "moons orbiting Saturn"
let naturalCount: String
switch approximateCount {
case -1: fallthrough
case 0:
    naturalCount = "no"
case 1..<5:
    naturalCount = "a few"
case 5..<12:
    naturalCount = "several"
case 12..<100:
    naturalCount = "dozens of"
case 100..<1000:
    naturalCount = "hundreds of"
default:
    naturalCount = "many"
}
print("There are \(naturalCount) \(countedThings).")

Tuple

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    print("\(somePoint) is at the origin")
case (_, 0):
    print("\(somePoint) is on the x-axis")
case (0, _):
    print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
    print("\(somePoint) is inside the box")
default:
    print("\(somePoint) is outside of the box")
}
// Prints "(1, 1) is inside the box"

Tuple let

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value of \(x)")
case (0, let y):
    print("on the y-axis with a y value of \(y)")
case (let x, let y):
    print("somewhere else at (\(x), \(y))")
}

where

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")
}

Labeled statements

label name: while condition {
    statements
}

Guard statement

guard always has an else clause

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    
    print("Hello \(name)!")
    
    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
    }
    
    print("I hope the weather is nice in \(location).")
}

greet(person: ["name": "John"])
// Prints "Hello John!"
// Prints "I hope the weather is nice near you."
greet(person: ["name": "Jane", "location": "Cupertino"])
// Prints "Hello Jane!"
// Prints "I hope the weather is nice in Cupertino."

Check API availability

if #available(iOS 10, macOS 10.12, *) {
    // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS
} else {
    // Fall back to earlier iOS and macOS APIs
}

Functions

func greet(p person: String) -> String {
    return "Hello, " + person + "!"
}

print(greet(p : "Anna"))

func greeting(_ person: String) -> String {
    return "Hello, " + person + "!"
}

print (greeting("Tom"))

Multiple return values

func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")

Optional tuple return values

func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

if let bounds = minMax(array : [Int]()) {
    print("min is \(bounds.min) and max is \(bounds.max)")
}else{
    print("Array is empty")
}

Default Parameter Values

func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    print ("\(parameterWithoutDefault), \(parameterWithDefault)")
}
someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6
someFunction(parameterWithoutDefault: 4)

Variadic Parameters (Equivalent to Java varargs)

func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5) // returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75) // returns 10.0, which is the arithmetic mean of these three numbers

In-Out Parameters (Like pointer in C)

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)") // Prints "someInt is now 107, and anotherInt is now 3"

Use Function Types

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

var mathFunction: (Int, Int) -> Int = addTwoInts
print("Result: \(mathFunction(2, 3))") // Prints "Result: 5"
mathFunction = multiplyTwoInts
print("Result: \(mathFunction(2, 3))") // Prints "Result: 6"
let anotherMathFunction = addTwoInts //Type can be inferred

Pass function as parameter types

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)   // Prints "Result: 8"
//Pass function as return types
func stepForward(_ input: Int) -> Int {
    return input + 1
}
func stepBackward(_ input: Int) -> Int {
    return input - 1
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    return backward ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
print("Counting to zero:")
//Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")

Nested functions

func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!

Closure

Basics

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward) // reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
reversedNames = names.sorted(by: {(s1: String, s2: String) -> Bool in
    return s1 > s2
})
reversedNames = names.sorted(by: {s1, s2 in return s1 > s2})
reversedNames = names.sorted(by: {s1, s2 in s1 > s2})
reversedNames = names.sorted(by: {$0 > $1})
reversedNames = names.sorted(by: >)

Trailing Closures

If you need to pass a closure expression to a function as the function’s final argument, it can be useful to write it as a trailing closure instead. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function.

reversedNames = names.sorted() { $0 > $1 }
reversedNames = names.sorted { $0 > $1 } //If closure is the only argument

Here’s how you can use the map(_:) method with a trailing closure to convert an array of Int values into an array of String values. The array [16, 58, 510] is used to create the new array ["OneSix", "FiveEight", "FiveOneZero"]:

let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

let closure = { (number : Int) -> String in
    var number = number
    var output = ""
    repeat {
        output = digitNames[number % 10]! + output
        number /= 10
    } while number > 0
    return output
}

let strings = numbers.map(closure)

let strings2 = numbers.map{ (number : Int) -> String in
    var number = number
    var output = ""
    repeat {
        output = digitNames[number % 10]! + output
        number /= 10
    } while number > 0
    return output
}

Capturing Values

A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

var incrementBy5 = makeIncrementer(forIncrement: 5)
print(incrementBy5()) // 5
print(incrementBy5()) // 10
var anotherIncrementBy5 = incrementBy5
print(anotherIncrementBy5()) // 15

var incrementBy10 = makeIncrementer(forIncrement: 10)
print (incrementBy10()) // 10
print (incrementBy10()) // 20
print (incrementBy10()) // 30

Escaping closure

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) { //completionHandler will be called later in the code after someFunctionWithEscapingClosure() is called 
    completionHandlers.append(completionHandler)
}

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure {
            print ("set x to 100")
            self.x = 100
        }
        someFunctionWithNonescapingClosure {
            print ("set x to 200")
            x = 200
        }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x) //200 , "set x to 100" is not printed

completionHandlers.first?()
print(instance.x) //100

Autoclosure

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count) // Prints "5"

let customerProvider = { customersInLine.remove(at: 0) } //type is () -> String
print(customersInLine.count) // Prints "5"

print("Now serving \(customerProvider())!") // Prints "Now serving Chris!"
print(customersInLine.count) // Prints "4"

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: {customersInLine.remove(at: 0)}) // Prints "Now serving Alex!"

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: {customersInLine.remove(at: 0)}) // Prints "Now serving Ewa!"
serve(customer: customersInLine.remove(at: 0)) // {} can be omitted due to @autoclosure. Prints "Now serving Barry!"

Enumeration

Basics

enum Beverage: CaseIterable {
    case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
for beverage in Beverage.allCases {
    print(beverage)
}

Associated Values

enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}

var productBarcode = Barcode.upc(8, 85909, 51226, 3)

switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
    print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
    print("QR code: \(productCode).")
}

Raw Values

enum Animal: String {
    case cat = "tom"
    case mouse = "jerry"
    case duck = "donald"
}

let aMouse = Animal.mouse
print(aMouse.rawValue)

enum Planet: Int, CaseIterable { //Implict raw values. the implicit value for each case is one more than the previous case. 
    case mercury = 100, venus, earth, mars, jupiter, saturn, uranus, neptune
}

for p in Planet.allCases{
    print ("\(p) = \(p.rawValue)") // 100 - 108
}

let possiblePlanet = Planet(rawValue: 102) //earth

Recursive Enumerations

enum ArithmeticExpression {
    case number(Int)
    indirect case addition(ArithmeticExpression, ArithmeticExpression)
    indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}

let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))

func evaluate(_ expression: ArithmeticExpression) -> Int {
    switch expression {
    case let .number(value):
        return value
    case let .addition(left, right):
        return evaluate(left) + evaluate(right)
    case let .multiplication(left, right):
        return evaluate(left) * evaluate(right)
    }
}

print(evaluate(product))

Structs vs Classes

Value types vs reference types

Structs are value types while Classes are reference types

var struct1 = MyStruct()
struct1.name = "old name"
var struct2 = struct1
struct2.name = "new name"
//Now struct1.name = "old name"

var class1 = MyClass()
class1.name = "old name"
var class2 = class1
class2.name = "new name"
//Now class1.name = "new name"

=== vs ==

Note that identical to (represented by three equals signs, or ===) doesn’t mean the same thing as equal to (represented by two equals signs, or ==).

let class1 = MyClass(name: "name")
let class2 = class1
let class3 = MyClass(name: "name")
class1 === class2 //True
class1 === class3 //False
class1 == class3 //Maybe True TODO

Lazy init

class DataImporter {
    
    var filename : String
    
    init() {
        print ("Init Data Importer")
        filename = "data.txt"
    }
    

    // the DataImporter class would provide data importing functionality here
}

class DataManager {
    lazy var importer = DataImporter()
    //var importer = DataImporter()
    func doStuff(){
        print ("Do stuff")
    }
    func doImport(){
        print (importer.filename)
    }
    
}

let manager = DataManager()
manager.doStuff()
manager.doImport()
// Prints Do stuff, Init Data Importer, data.txt with lazy keyword
// Prints Init Data Importer, Do stuff, data.txt without lazy keyword

Computed Properties

struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}

didSet and willSet

class StepCounter {
    var totalSteps: Int = 0 {
        willSet {
            print("About to set totalSteps to \(newValue), add to \(totalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                print("Added \(totalSteps - oldValue) steps")
            }
        }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps

Type Properties

struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}

print(SomeStructure.storedTypeProperty) // Prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty) // Prints "Another value."
print(SomeStructure.computedTypeProperty) // Prints "1"
SomeStructure.computedTypeProperty = 6 //Compilation error as computedTypeProperty is a read only property

Methods

mutating

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}

self

struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}

enum TriStateSwitch {
    case off, low, high
    mutating func next() {
        switch self {
        case .off:
            self = .low
        case .low:
            self = .high
        case .high:
            self = .off
        }
    }
}
var ovenLight = TriStateSwitch.low
ovenLight.next() // ovenLight is now equal to .high
ovenLight.next() // ovenLight is now equal to .off

Type methods

class SomeClass {
    class func someTypeMethod1() {
        print ("calling method 1")
    }
    
    static func someTypeMethod2() {
        print ("calling method 2")
    }
}
SomeClass.someTypeMethod1() //Prints "calling method 1"
SomeClass.someTypeMethod2() //Prints "calling method 2"

Subscripts

struct TimesTable {
    let multiplier: Int
    subscript(index: Int) -> Int {
        return multiplier * index
    }
}
let threeTimesTable = TimesTable(multiplier: 3)
print("six times three is \(threeTimesTable[6])")

Multiple input parameters

struct Matrix {
    let rows: Int, columns: Int
    var grid: [Double]
    init(rows: Int, columns: Int) {
        self.rows = rows
        self.columns = columns
        grid = Array(repeating: 0.0, count: rows * columns)
    }
    func indexIsValid(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }
    subscript(row: Int, column: Int) -> Double {
        get {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValid(row: row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}
 
var matrix = Matrix(rows: 2, columns: 2)
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
 
print (matrix[0, 1]) //Prints 1.5
print (matrix[2, 2]) //Error: Index out of range

Inheritance

Override properties

class Vehicle {
    var currentSpeed = 0.0
    var description: String {
        return "traveling at \(currentSpeed) miles per hour"
    }
    func makeNoise() {
        // do nothing - an arbitrary vehicle doesn't necessarily make a noise
    }
}

class Car: Vehicle {
    var gear = 1
    override var description: String {
        return super.description + " in gear \(gear)"
    }
}

let car = Car()
car.description

Overriding property observer

class AutomaticCar: Car {
    override var currentSpeed: Double {
        didSet {
            gear = Int(currentSpeed / 10.0) + 1
        }
    }
}

let automatic = AutomaticCar()
automatic.currentSpeed = 35.0
print("AutomaticCar: \(automatic.description)")

Initialization

struct Celsius {
    var temperatureInCelsius: Double
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0) // boilingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15) // freezingPointOfWater.temperatureInCelsius is 0.0

Memberwise Initializers for Structure Types

struct Size {
    var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0) //Good 

class Size2 {
    var width = 0.0, height = 0.0
}
let twoByTwo2 = Size2(width: 2.0, height: 2.0) //Compilation error
Clone this wiki locally