Swift5.0新特性

//: Playground - noun: a place where people can play
import UIKit

let max = 10

var current = 0

//类型标注

var welcomeMessage: String

var red, green, blue, yellow: Double

//十进制17

let decimalInteger = 17

let binaryInteger = 0b10001 // 17 in binary notation

let octalInteger = 0o21 // 17 in octal notation

let hexadecimalInteger = 0x11 // 17 in hexadecimal notation

red = 1.25e2 //意味着 1.25 x 102, 或者 125.0  .

green = 1.25e-2 //意味着 1.25 x 10-2, 或者 0.0125

blue = 0xFp2 //意味着 15 x 22, 或者 60.0 .

//yellow = 0xFp - 2 //意味着 15 x 2-2, 或者 3.75 .

//let cannotBeNegative: UInt8 = -1

// UInt8 cannot store negative numbers, and so this will report an error

//let tooBig: Int8 = Int8.max + 1

// Int8 cannot store a number larger than its maximum value,

// and so this will also report an error

let twoThousand: UInt16 = 2_000

let one: UInt8 = 1

let twoThousandAndOne = twoThousand + UInt16( one)

//布尔值

let orangesAreOrange = true

let turnipsAreDelicious = false

if turnipsAreDelicious {

    print("Mmm, tasty turnips!")

} else {

    print("Eww, turnips are horrible.")

}

//元组

let http404Error = (404, "Not Found")

let (statusCode, statusMessage) = http404Error

print("The status code is \(statusCode)")

// prints "The status code is 404"

print("The status message is \(statusMessage)")

// prints "The status message is Not Found"

print("The status code is \(http404Error.0)")

// prints "The status code is 404"

print("The status message is \(http404Error.1)")

// prints "The status message is Not Found"

let http200Status = (statusCode: 200, description: "OK")

print("The status code is \(http200Status.statusCode)")

// prints "The status code is 200"

print("The status message is \(http200Status.description)")

// prints "The status message is OK"

//12 可选项  这里有一个值,他等于x 或者 这里根本没有值

let possibleNumber = "123"

//let convertedNumber = Int(possibleNumber)

let convertedNumber: Int?

convertedNumber = Int(possibleNumber);

var serverResponseCode: Int? = 404

// serverResponseCode contains an actual Int value of 404

serverResponseCode = nil

// serverResponseCode now contains no value

var surveyAnswer: String? // surveyAnswer is automatically set to nil

if convertedNumber != nil {

    print("convertedNumber has an integer value of \(convertedNumber!).")

    print("convertedNumber has an integer value of \(convertedNumber ?? 3).")

}

// prints "convertedNumber has an integer value of 123."

//12.3 可选项绑定

if let actualNumber = Int(possibleNumber) {

    print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")

} else {

    print("\'\(possibleNumber)\' could not be converted to an integer")

}

// prints "'123' has an integer value of 123"

let firstNumber = Int("4")

let secondNumber = Int("42")

if (firstNumber != nil), (secondNumber != nil) {

    print("\(firstNumber!) < \(secondNumber!)")

}

//或者 这样用 就不需要 可选值的强制展开  因为firstNumber这个就不是可选值了

if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 {

    print("\(firstNumber) < \(secondNumber) < 100")

}

//12.4 隐式展开可选项

let possibleString: String? = "An optional string."

let forcedString: String = possibleString! // requires an exclamation mark

let assumedString: String! = "An implicitly unwrapped optional string."

let implicitString: String = assumedString // no need for an exclamation mark

if assumedString != nil {

    print(assumedString) //

    print(assumedString!) //自己还要展开下

    print(implicitString) //复制的变量不要展开

}

// prints "An implicitly unwrapped optional string."

if let definiteString = assumedString {

    print(definiteString)

}

// prints "An implicitly unwrapped optional string."

//13 错误处理

func canThrowAnError() throws {

    // this function may or may not throw an error

}

do {

    try canThrowAnError()

    // no error was thrown

} catch {

    // an error was thrown

}

//14 断言

var age = 3

assert(age >= 0, "A person's age cannot be less than zero")

age = -3

if age > 10 {

    print("You can ride the roller-coaster or the ferris wheel.")

} else if age > 0 {

    print("You can ride the ferris wheel.")

} else {

//    assertionFailure("A person's age can't be less than zero.")

}

//let index = -3

//precondition(index > 0, "Index must be greater than zero.")

//////基本运算符//////

let (x, y) = (1, 2)

//与 Objective-C 和 C 不同,Swift 的赋值符号自身不会返回值。下面的语句是不合法的:

//if x = y {

//    // 这是不合法的, 因为 x = y 并不会返回任何值。

//}

if x == y {

}

//5比较运算符

(1, "zebra") < (2, "apple")   // true because 1 is less than 2

(3, "apple") < (3, "bird")    // true because 3 is equal to 3, and "apple" is less than "bird"

(4, "dog") == (4, "dog")      // true because 4 is equal to 4, and "dog" is equal to "dog"

//7 合并空值运算符 ( a ?? b )

let defaultColorName = "red"

var userDefinedColorName: String? // defaults to nil

var colorNameToUse = userDefinedColorName ?? defaultColorName

userDefinedColorName = "green"

colorNameToUse = userDefinedColorName ?? defaultColorName

//8闭区间运算符

for index in 1...5 {

    print("\(index) times 5 is \(index * 5)")

}

// 1 times 5 is 5

// 2 times 5 is 10

// 3 times 5 is 15

// 4 times 5 is 20

// 5 times 5 is 25

let names = ["Anna", "Alex", "Brian", "Jack"]

let count = names.count

for i in 0..<count {

    print("Person \(i + 1) is called \(names[i])")

}

// Person 1 is called Anna

// Person 2 is called Alex

// Person 3 is called Brian

// Person 4 is called Jack

////////////字符串和字符////////////

//多行字符串字面量

let quotation = """

    The White Rabbit put on his spectacles.  "Where shall I begin,

please your Majesty?" he asked.

"Begin at the beginning," the King said gravely, "and go on

till you come to the end; then stop."

"""

//1.3 初始化一个空字符串

var emptyString = ""              // empty string literal

var anotherEmptyString = String()  // initializer syntax

// these two strings are both empty, and are equivalent to each other

if emptyString.isEmpty {

    print("Nothing to see here")

}

// prints "Nothing to see here"

//5.操作字符 Character 和Sring交互

for character in "Dog!?" {

    print(character)

}

// D

// o

// g

// !

// ?

let catCharacters: [Character] = ["C", "a", "t", "!", "?"]

let catString = String(catCharacters)

print(catString)

//7.字符串插值

let multiplier = 3

let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"

// message is "3 times 2.5 is 7.5"

print(#"Write an interpolated string in Swift using \(multiplier)."#)

// Prints "Write an interpolated string in Swift using \(multiplier)."

print(#"Write an interpolated string in Swift using \#(multiplier)."#)

print(#"6 times 7 is \#(6 * 7)."#)

// Prints "6 times 7 is 42."

//9 字符统计

let unusualMenagerie = "Koala ?, Snail ?, Penguin ?, Dromedary ?"

print("unusualMenagerie has \(unusualMenagerie.count) characters")

// Prints "unusualMenagerie has 40 characters"

//10.1字符串索引

let greeting = "Guten Tag!"

greeting[greeting.startIndex]

// G

greeting[greeting.index(before: greeting.endIndex)]

// ! 最后一个字符

greeting[greeting.index(after: greeting.startIndex)]

// u

let index = greeting.index(greeting.startIndex, offsetBy: 7)

greeting[index]

// a

for index in greeting.indices {

    print("\(greeting[index]) ", terminator: "")

}

// Prints "G u t e n   T a g ! "

//10.2 插入和删除

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"

//11.子字符串

let greeting1 = "Hello, world!"

let index1 = greeting1.firstIndex(of: ",") ?? greeting1.endIndex

let beginning = greeting1[..<index1]

// beginning is "Hello"

// Convert the result to a String for long-term storage.

let newString = String(beginning)

//12.1 字符串和字符相等性

let quotation1 = "We're a lot alike, you and I."

let sameQuotation = "We're a lot alike, you and I."

if quotation1 == sameQuotation {

    print("These two strings are considered equal")

}

// prints "These two strings are considered equal"

//12.2 前缀和后缀相等性

let romeoAndJuliet = [

    "Act 1 Scene 1: Verona, A public place",

    "Act 1 Scene 2: Capulet's mansion",

    "Act 1 Scene 3: A room in Capulet's mansion",

    "Act 1 Scene 4: A street outside Capulet's mansion",

    "Act 1 Scene 5: The Great Hall in Capulet's mansion",

    "Act 2 Scene 1: Outside Capulet's mansion",

    "Act 2 Scene 2: Capulet's orchard",

    "Act 2 Scene 3: Outside Friar Lawrence's cell",

    "Act 2 Scene 4: A street in Verona",

    "Act 2 Scene 5: Capulet's mansion",

    "Act 2 Scene 6: Friar Lawrence's cell"

]

var act1SceneCount = 0

for scene in romeoAndJuliet {

    if scene.hasPrefix("Act 1 ") {

        act1SceneCount += 1

    }

}

print("There are \(act1SceneCount) scenes in Act 1")

var mansionCount = 0

var cellCount = 0

for scene in romeoAndJuliet {

    if scene.hasSuffix("Capulet's mansion") {

        mansionCount += 1

    } else if scene.hasSuffix("Friar Lawrence's cell") {

        cellCount += 1

    }

}

print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")

// Prints "6 mansion scenes; 2 cell scenes"

/////////集合类型/////////

//2.2创建一个空数组

var someInts = [Int]()

print("someInts is of type [Int] with \(someInts.count) items.")

// prints "someInts is of type [Int] with 0 items."

someInts.append(3)

// someInts now contains 1 value of type Int

someInts = [] //如果内容已经提供了类型信息,可以用这个方法创建空数组

// someInts is now an empty array, but is still of type [Int]

//2.4 通过连接两个数组来创建数组

var threeDoubles = Array(repeating: 0.0, count: 3)

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]

//2.5 使用数组字面量创建数组

var shoppingList: [String] = ["Eggs", "Milk"]

shoppingList = ["Eggs", "Milk"]

//2.6访问和修改数组

if shoppingList.isEmpty {

    print("The shopping list is empty.")

} else {

    print("The shopping list is not empty.")

}

var firstItem = shoppingList[0]

// firstItem is equal to "Eggs"

shoppingList[0] = "Six eggs"

shoppingList.insert("Maple Syrup", at: 0)

let mapleSyrup = shoppingList.remove(at: 0)

for item in shoppingList {

    print(item)

}

shoppingList = ["Six eggs", "Milk", "Flour", "Baking Powder", "Bananas"]

for (index, value) in shoppingList.enumerated() {

    print("Item \(index + 1): \(value)")

}

// Item 1: Six eggs

// Item 2: Milk

// Item 3: Flour

// Item 4: Baking Powder

// Item 5: Bananas

//3.3创建并初始化一个空合集

var letters = Set<Character>()

print("letters is of type Set<Character> with \(letters.count) items.")

// prints "letters is of type Set<Character> with 0 items."

letters.insert("a")

// letters now contains 1 value of type Character

letters = []

// letters is now an empty set, but is still of type Set<Character>

var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]

// favoriteGenres has been initialized with three initial items

var favoriteGenres2: Set = ["Rock", "Classical", "Hip hop"]

//3.5 访问和修改合集

if favoriteGenres.isEmpty {

    print("As far as music goes, I'm not picky.")

} else {

    print("I have particular music preferences.")

}

favoriteGenres.insert("Jazz")

if let removedGenre = favoriteGenres.remove("Rock") {

    print("\(removedGenre)? I'm over it.")

} else {

    print("I never much cared for that.")

}

// prints "Rock? I'm over it.

// favoriteGenres now contains 4 items

if favoriteGenres.contains("Funk") {

    print("I get up on the good foot.")

} else {

    print("It's too funky in here.")

}

// prints "It's too funky in here.

for genre in favoriteGenres {

    print("\(genre)")

}

// Classical

// Jazz

// Hip hop

for genre in favoriteGenres.sorted() {

    print("\(genre)")

}

// Classical

// Hip hop

// Jazz

//4.执行合集操作

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]

//5.字典

//5.2 创建一个空字典

var namesOfIntegers = [Int: String]()

var namesOfIntegers2 = [String: String]()

namesOfIntegers[16] = "sixteen"

// namesOfIntegers now contains 1 key-value pair

namesOfIntegers = [:]

// namesOfIntegers is once again an empty dictionary of type [Int: String]

var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

var airports2 = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

//5.4访问和修改字典

print("The airports dictionary contains \(airports.count) items.")

if airports.isEmpty {

    print("The airports dictionary is empty.")

} else {

    print("The airports dictionary is not empty.")

}

airports["LHR"] = "London"

airports["LHR"] = "London Heathrow"

// the value for "LHR" has been changed to "London Heathrow"

if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {

    print("The old value for DUB was \(oldValue).")

}

// prints "The old value for DUB was Dublin."

if let airportName = airports["DUB"] {

    print("The name of the airport is \(airportName).")

} else {

    print("That airport is not in the airports dictionary.")

}

// prints "The name of the airport is Dublin Airport."

airports["APL"] = nil

// APL has now been removed from the dictionary

if let removedValue = airports.removeValue(forKey: "DUB") {

    print("The removed airport's name is \(removedValue).")

} else {

    print("The airports dictionary does not contain a value for DUB.")

}

// Prints "The removed airport's name is Dublin Airport.

for (airportCode, airportName) in airports {

    print("\(airportCode): \(airportName)")

}

// YYZ: Toronto Pearson

// LHR: London Heathrow

for airportCode in airports.keys {

    print("Airport code: \(airportCode)")

}

// Airport code: YYZ

// Airport code: LHR

for airportName in airports.values {

    print("Airport name: \(airportName)")

}

// Airport name: Toronto Pearson

// Airport name: London Heathrow

//排序

let airportCodes = [String](airports.keys).sorted()

// airportCodes is ["YYZ", "LHR"]

let airportNames = [String](airports.values)

// airportNames is ["Toronto Pearson", "London Heathrow"]

////////////控制流////////////

//1\. For-in 循环

for index in 1...5 {

    print("\(index) times 5 is \(index * 5)")

}

// 1 times 5 is 5

// 2 times 5 is 10

// 3 times 5 is 15

// 4 times 5 is 20

// 5 times 5 is 25

let base = 3

let power = 10

var answer = 1

//用下划线来取代遍历名以忽略值

for _ in 1...power {

    answer *= base

}

print("\(base) to the power of \(power) is \(answer)")

// prints "3 to the power of 10 is 59049"

let minutes = 60

for tickMark in 0..<minutes {

    // render the tick mark each minute (60 times)

}

let minuteInterval = 5

for tickMark in stride(from: 0, to: minutes, by: minuteInterval) {

    // render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55)

}

let hours = 12

let hourInterval = 3

for tickMark in stride(from: 3, through: hours, by: hourInterval) {

    // render the tick mark every 3 hours (3, 6, 9, 12)

}

//2.While 循环

//3.条件语句

//3.2Switch

let someCharacter: Character = "z"

switch someCharacter {

case "a":

    print("The first letter of the alphabet")

case "z":

    print("The last letter of the alphabet")

default:

    print("Some other character")

}

// Prints "The last letter of the alphabet"

//let anotherCharacter: Character = "a"

//switch anotherCharacter {

//case "a":

//case "A":

//    print("The letter A")

//default:

//    print("Not the letter A")

//}

//// this will report a compile-time error

let anotherCharacter: Character = "a"

switch anotherCharacter {

case "a", "A":

    print("The letter A")

default:

    print("Not the letter A")

}

// Prints "The letter A"

let approximateCount = 62

let countedThings = "moons orbiting Saturn"

var naturalCount: String

switch approximateCount {

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

// prints "There are dozens of moons orbiting Saturn."

let somePoint = (1, 1)

switch somePoint {

case (0, 0):

    print("(0, 0) is at the origin")

case (_, 0):

    print("(\(somePoint.0), 0) is on the x-axis")

case (0, _):

    print("(0, \(somePoint.1)) is on the y-axis")

case (-2...2, -2...2):

    print("(\(somePoint.0), \(somePoint.1)) is inside the box")

default:

    print("(\(somePoint.0), \(somePoint.1)) is outside of the box")

}

// prints "(1, 1) is inside the box"

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, y):

    print("somewhere else at (\(x), \(y))")

}

// prints "on the x-axis with an x value of 2"

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"

//4.控制转移语句

let puzzleInput = "great minds think alike"

var puzzleOutput = ""

let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]

for character in puzzleInput {

    if charactersToRemove.contains(character) {

        continue

    } else {

        puzzleOutput.append(character)

    }

}

print(puzzleOutput)

// Prints "grtmndsthnklk"

//使用 fallthrough 关键字来“贯穿到” default 情况

let integerToDescribe = 5

var description = "The number \(integerToDescribe) is"

switch integerToDescribe {

case 2, 3, 5, 7, 11, 13, 17, 19:

    description += " a prime number, and also"

    fallthrough

default:

    description += " an integer."

}

print(description)

// prints "The number 5 is a prime number, and also an integer."

//5\. 提前退出

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."

//////////////函数//////////////

//1.定义和调用函数

func greet(person: String) -> String {

    let greeting = "Hello, " + person + "!"

    return greeting

}

print(greet(person: "Anna"))

// Prints "Hello, Anna!"

print(greet(person: "Brian"))

// Prints "Hello, Brian!"

func greetAgain(person: String) -> String {

    return "Hello again, " + person + "!"

}

print(greetAgain(person: "Anna"))

//2.1无形式参数的函数

func sayHelloWorld() -> String {

    return "hello, world"

}

print(sayHelloWorld())

// prints "hello, world"

//2.2多形式参数的函数

func greet(person: String, alreadyGreeted: Bool) -> String {

    if alreadyGreeted {

        return greetAgain(person: person)

    } else {

        return greet(person: person)

    }

}

print(greet(person: "Tim", alreadyGreeted: true))

// Prints "Hello again, Tim!"

//2.3 无返回值的函数

func greet1(person: String) {

    print("Hello, \(person)!")

}

greet1(person: "Dave")

// Prints "Hello, Dave!

//2.4多返回值的函数

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

// Prints "min is -6 and max is 109"

//2.5 可选元组返回类型

func minMax1(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 = minMax1(array: [8, -6, 2, 109, 3, 71]) {

    print("min is \(bounds.min) and max is \(bounds.max)")

}

// Prints "min is -6 and max is 109"

//3.函数实际参数标签和形式参数名

//形式参数使用它们的形式参数名作为实际参数标签。

func someFunction(firstParameterName: Int, secondParameterName: Int) {

    // In the function body, firstParameterName and secondParameterName

    // refer to the argument values for the first and second parameters.

}

someFunction(firstParameterName: 1, secondParameterName: 2)

//3.1指定实际参数标签

func someFunction(argumentLabel parameterName: Int) {

    // In the function body, parameterName refers to the argument value

    // for that parameter.

}

func greet(person: String, from hometown: String) -> String {

    return "Hello \(person)!  Glad you could visit from \(hometown)."

}

print(greet(person: "Bill", from: "Cupertino"))

// Prints "Hello Bill!  Glad you could visit from Cupertino."

//3.2 省略实际参数标签(调用的时候省略)

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {

    // In the function body, firstParameterName and secondParameterName

    // refer to the argument values for the first and second parameters.

    print("_,\(secondParameterName)");

}

someFunction(1, secondParameterName: 2)

func someFunction(_ firstParameterName: Int, _ secondParameterName: Int) {

    // In the function body, firstParameterName and secondParameterName

    // refer to the argument values for the first and second parameters.

    print("_,_");

}

someFunction(1, 2)

//3.3 默认形式参数值

func someFunction(parameterWithDefault: Int = 12) {

    // In the function body, if no arguments are passed to the function

    // call, the value of parameterWithDefault is 12.

}

someFunction(parameterWithDefault: 6) // parameterWithDefault is 6

someFunction() // parameterWithDefault is 12

//3.4 可变形式参数

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

//3.5 输入输出形式参数  inout   &

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"

//4\. 函数类型

//函数类型是 (Int, Int) -> Int

func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {

    return a * b

}

func addTwoInts(_ a: Int, _ b: Int) -> Int {

    return a + b

}

//函数类型是 () -> Void

func printHelloWorld() {

    print("hello, world")

}

//4.1 使用函数类型

var mathFunction: (Int, Int) -> Int = addTwoInts

var mathFuction1 = addTwoInts

print("Result: \(mathFunction(2, 3))")

mathFunction = multiplyTwoInts

print("Result: \(mathFunction(2, 3))")

//4.2 函数类型作为形式参数类型

func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {

    print("Result: \(mathFunction(a, b))")

}

printMathResult(addTwoInts, 3, 5)

// Prints "Result: 8"

//4.3 函数类型作为返回类型

//函数的类型都是 (Int) -> Int

func stepForward(_ input: Int) -> Int {

    return input + 1

}

func stepBackward(_ input: Int) -> Int {

    return input - 1

}

func chooseStepFunction(backwards: Bool) -> (Int) -> Int {

    return backwards ? stepBackward : stepForward

}

var currentValue = 3

let moveNearerToZero = chooseStepFunction(backwards: currentValue > 0)

// moveNearerToZero now refers to the stepBackward() function

print("Counting to zero:")

// Counting to zero:

while currentValue != 0 {

    print("\(currentValue)... ")

    currentValue = moveNearerToZero(currentValue)

}

print("zero!")

// 3...

// 2...

// 1...

// zero!

//5.内嵌函数

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 currentValue1 = -4

let moveNearerToZero1 = chooseStepFunction(backward: currentValue > 0)

// moveNearerToZero now refers to the nested stepForward() function

while currentValue1 != 0 {

    print("\(currentValue1)... ")

    currentValue1 = moveNearerToZero1(currentValue1)

}

print("zero!")

// -4...

// -3...

// -2...

// -1...

// zero!

////////////闭包////////////

//闭包是可以在你的代码中被传递和引用的功能性独立模块。Swift 中的闭包和 C  以及 Objective-C 中的 blocks 很像,还有其他语言中的匿名函数也类似。

//1.闭包表达式 闭包表达式是一种在简短行内就能写完闭包的语法

//1.1Sorted 方法

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"]

//1.2 闭包表达式语法

//{ (parameters) -> (return type) in

//    statements

//}

reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in

    return s1 > s2

})

//1.3 从语境中推断类型

reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )

//1.4 从单表达式闭包隐式返回 删除return

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

//1.5 简写的实际参数名

//Swift 自动对行内闭包提供简写实际参数名,你也可以通过 $0 , $1 , $2 等名字来引用闭包的实际参数值。

reversedNames = names.sorted(by: { $0 > $1 } )

//1.6 运算符函数

reversedNames = names.sorted(by: >)

//2.尾随闭包

func someFunctionThatTakesAClosure(closure:() -> Void){

    //function body goes here

}

//here's how you call this function without using a trailing closure

someFunctionThatTakesAClosure(closure: {

    //closure's body goes here

})

//here's how you call this function with a trailing closure instead

//尾随闭包使用

someFunctionThatTakesAClosure() {

    // trailing closure's body goes here

}

//如果你需要将一个很长的闭包表达式作为函数最后一个实际参数传递给函数,使用尾随闭包将增强函数的可读性。尾随闭包是一个被书写在函数形式参数的括号外面(后面)的闭包表达式:

reversedNames = names.sorted() { $0 > $1 }

//如果闭包表达式作为函数的唯一实际参数传入,而你又使用了尾随闭包的语法,那你就不需要在函数名后边写圆括号了

reversedNames = names.sorted { $0 > $1 }

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]

//、Swift 的 Array 类型中有一个以闭包表达式为唯一的实际参数的 map(_:) 方法。数组中每一个元素调用一次该闭包,并且返回该元素所映射的值(有可能是其他类型)。具体的映射方式和返回值的类型有闭包来指定

let strings = numbers.map {

    (number) -> String in

    var number = number

    var output = ""

    repeat {

        output = digitNames[number % 10]! + output

        number /= 10

    } while number > 0

    return output

}

// strings is inferred to be of type [String]

// its value is ["OneSix", "FiveEight", "FiveOneZero"]

//3.捕获值

//[https://www.cnswift.org/closures](https://www.cnswift.org/closures)    stop hehe

///////////枚举///////////

enum CompassPoint {

    case north

    case south

    case east

    case west

}

enum Planet {

    case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune

}

var directionToHead = CompassPoint.west

//初始化时 directionToHead的类型会被推断出来 不需要添加CompassPoint

directionToHead = .east

directionToHead = .south

switch directionToHead {

case .north:

    print("Lots of planets have a north")

case .south:

    print("Watch out for penguins")

case .east:

    print("Where the sun rises")

case .west:

    print("Where the skies are blue")

}

// prints "Watch out for penguins"

let somePlanet = Planet.earth

switch somePlanet {

case .earth:

    print("Mostly harmless")

default:

    print("Not a safe place for humans")

}

// Prints "Mostly harmless"

//4.遍历枚举情况(case)  CaseIterable  allCases

enum Beverage: CaseIterable {

    case coffee, tea, juice

}

let numberOfChoices = Beverage.allCases.count

print("\(numberOfChoices) beverages available")

// Prints "3 beverages available"

for beverage in Beverage.allCases {

    print(beverage)

}

// coffee

// tea

// juic

////////////类和结构体////////////

struct Resolution {

    var width = 0

    var height = 0

}

class VideoMode {

    var resolution = Resolution()

    var interlaced = false

    var frameRate = 0.0

    var name: String?

}

//1.2类与结构体实例

let someResolution = Resolution()

let someVideoMode = VideoMode()

print("The width of someVideoMode is \(someVideoMode.resolution.width)")

//1.4 结构体类型的成员初始化器

let vga = Resolution(width: 640, height: 480)

//2.结构体和枚举是值类型

let hd = Resolution(width: 1920, height: 1080)

var cinema = hd

cinema.width = 2048

print("cinema is now \(cinema.width) pixels wide")

//println "cinema is now 2048 pixels wide"

print("hd is still \(hd.width) pixels wide")

// prints "hd is still 1920 pixels wide"

//3.类是引用类型

let tenEighty = VideoMode()

tenEighty.resolution = hd

tenEighty.interlaced = true

tenEighty.name = "1080i"

tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty

alsoTenEighty.frameRate = 30.0

print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")

// prints "The frameRate property of tenEighty is now 30.0"

//利用这两个恒等运算符来检查两个常量或者变量是否引用相同的实例:

if tenEighty === alsoTenEighty {

    print("tenEighty and alsoTenEighty refer to the same VideoMode instance.")

}

// prints "tenEighty and alsoTenEighty refer to the same VideoMode instance."

/////////////属性/////////////

//[https://www.cnswift.org/properties](https://www.cnswift.org/properties)

//1.存储属性

struct FixedLengthRange {

    var firstValue: Int

    let length: Int

}

var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)

// the range represents integer values 0, 1, and 2

rangeOfThreeItems.firstValue = 6

// the range now represents integer values 6, 7, and 8

//let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)

// this range represents integer values 0, 1, 2, and 3

//rangeOfFourItems.firstValue = 6

// this will report an error, even though firstValue is a variable property

//1.2延迟存储属性  lazy

class DataImporter {

    //DataImporter is a class to import data from an external file.

    //The class is assumed to take a non-trivial amount of time to initialize.

    var fileName = "data.txt"

    // the DataImporter class would provide data importing functionality here

}

class DataManager {

    lazy var importer = DataImporter()

    var data = [String]()

    // the DataManager class would provide data management functionality here

}

let manager = DataManager()

manager.data.append("Some data")

manager.data.append("Some more data")

//使用时 才创建

print(manager.importer.fileName)

// the DataImporter instance for the importer property has now been created

// prints "data.txt"

//1.3 存储属性与实例变量 oc有name _name  swift没有只有属性

//2.计算属性

struct Point {

    var x = 0.0, y = 0.0

}

struct Size {

    var width = 0.0, height = 0.0

}

struct Rect {

    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(newCenter) {

            origin.x = newCenter.x - (size.width / 2)

            origin.y = newCenter.y - (size.height / 2)

        }

    }

}

var square = Rect(origin: Point(x: 0.0, y: 0.0),

                  size: Size(width: 10.0, height: 10.0))

let initialSquareCenter = square.center

square.center = Point(x: 15.0, y: 15.0)

print("square.origin is now at (\(square.origin.x), \(square.origin.y))")

// prints "square.origin is now at (10.0, 10.0)"

//2.1 简写设置器(setter)声明

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)

        }

    }

}

//2.2 缩写读取器(getter)声明

struct CompactRect {

    var origin = Point()

    var size = Size()

    var center: Point {

        get {

            return Point(x: origin.x + (size.width / 2),

                  y: origin.y + (size.height / 2))

        }

        set {

            origin.x = newValue.x - (size.width / 2)

            origin.y = newValue.y - (size.height / 2)

        }

    }

}

//2.3只读计算属性

struct Cuboid {

    var width = 0.0, height = 0.0, depth = 0.0

    var volume: Double {

        return width * height * depth

    }

}

let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)

print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")

//3.属性观察者  willSet 会在该值被存储之前被调用。 didSet 会在一个新值被存储后被调用。

class StepCounter {

    var totalSteps: Int = 0 {

        willSet(newTotalSteps) {

            print("About to set totalSteps to \(newTotalSteps)")

        }

        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

//5.类型属性 使用 static 关键字来开一类型属性

//使用 static 关键字来开一类型属性。对于类类型的计算类型属性,你可以使用 class 关键字来允许子类重写父类的实现

struct SomeStructure {

    static var storedTypeProperty = "Some value."

    static var computedTypeProperty: Int {

        return 1

    }

}

enum SomeEnumeration {

    static var storedTypeProperty = "Some value."

    static var computedTypeProperty: Int {

        return 6

    }

}

class SomeClass {

    static var storedTypeProperty = "Some value."

    static var computedTypeProperty: Int {

        return 27

    }

    class var overrideableComputedTypeProperty: Int {

        return 107

    }

}

print(SomeStructure.storedTypeProperty)

// prints "Some value."

SomeStructure.storedTypeProperty = "Another value."

print(SomeStructure.storedTypeProperty)

// prints "Another value."

print(SomeEnumeration.computedTypeProperty)

// prints "6"

print(SomeClass.computedTypeProperty)

// prints "27"

//////////////方法//////////////

//1.实例方法

class Counter {

    var count = 0

    func increment() {

        count += 1

    }

    func increment(by amount: Int) {

        count += amount

    }

    func reset() {

        count = 0

    }

}

let counter = Counter()

// the initial counter value is 0

counter.increment()

// the counter's value is now 1

counter.increment(by: 5)

// the counter's value is now 6

counter.reset()

// the counter's value is now 0

//1.1 self  无法区分用self

struct Point1 {

    var x = 0.0, y = 0.0

    func isToTheRightOf(x: Double) -> Bool {

        return self.x > x

    }

}

let somePoint = Point1(x: 4.0, y: 5.0)

if somePoint.isToTheRightOf(x: 1.0) {

    print("This point is to the right of the line where x == 1.0")

}

// Prints "This point is to the right of the line where x == 1.0"

//1.2在实例方法中修改值类型

//结构体和枚举是值类型。默认情况下,值类型属性不能被自身的实例方法修改。 一定要加mutating

struct Point2 {

    var x = 0.0, y = 0.0

    mutating func moveBy(x deltaX: Double, y deltaY: Double) {

        x += deltaX

        y += deltaY

    }

}

var somePoint2 = Point2(x: 1.0, y: 1.0)

somePoint2.moveBy(x: 2.0, y: 3.0)

print("The point is now at (\(somePoint2.x), \(somePoint2.y))")

// prints "The point is now at (3.0, 4.0)"

let fixedPoint = Point2(x: 3.0, y: 3.0)

//fixedPoint.moveBy(x: 2.0, y: 3.0)

// this will report an error

//1.3 在异变方法里指定自身

struct Point3 {

    var x = 0.0, y = 0.0

    mutating func moveBy(x deltaX: Double, y deltaY: Double) {

        self = Point3(x: x + deltaX, y: y + deltaY)

    }

}

//2 类型方法

//通过在 func关键字之前使用 static关键字来明确一个类型方法。类同样可以使用 class关键字来允许子类重写父类对类型方法的实现。

class SomeClass1 {

    class func someTypeMethod() {

        // type method implementation goes here

    }

}

SomeClass1.someTypeMethod()

/////////下标/////////

//1.下标的语法

//subscript(index: Int) -> Int {

//    get {

//        // return an appropriate subscript value here

//    }

//    set(newValue) {

//        // perform a suitable setting action here

//    }

//}

struct TimesTable {

    let multiplier: Int

    subscript(index: Int) -> Int {

        return multiplier * index

    }

}

let threeTimesTable = TimesTable(multiplier: 3)

print("six times three is \(threeTimesTable[6])")

//3.下标选项

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

//let someValue = matrix[2, 2]

//4.类型下标

//enum Planet1: Int {

//    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune

//    subscript(n: Int) -> Planet1 {

//        return Planet1(rawValue: n)!

//    }

//}

//let mars = Planet1[4]

//print(mars)

/////////////继承/////////////

//1.定义一个基类

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

    }

}

let someVehicle = Vehicle()

print("Vehicle: \(someVehicle.description)")

//2.子类

class Bicycle: Vehicle {

    var hasBasket = false

}

let bicycle = Bicycle()

bicycle.hasBasket = true

bicycle.currentSpeed = 15.0

print("Bicycle: \(bicycle.description)")

class Tandem: Bicycle {

    var currentNumberOfPassengers = 0

}

let tandem = Tandem()

tandem.hasBasket = true

tandem.currentNumberOfPassengers = 2

tandem.currentSpeed = 22.0

print("Tandem: \(tandem.description)")

// Tandem: traveling at 22.0 miles per hour

//3.重写 override

//3.2重写方法

class Train: Vehicle {

    override func makeNoise() {

        print("Choo Choo")

    }

}

let train = Train()

train.makeNoise()

// prints "Choo Choo"

//3.3重写属性

class Car: Vehicle {

    var gear = 1

    override var description: String {

        return super.description + " in gear \(gear)"

    }

}

let car = Car()

car.currentSpeed = 25.0

car.gear = 3

print("Car: \(car.description)")

// Car: traveling at 25.0 miles per hour in gear 3

//3.4 重写属性观察器

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

// AutomaticCar: traveling at 35.0 miles per hour in gear 4

//4.阻止重写

//final var , final func , final class func , final subscript

/////////////初始化/////////////

//1.为存储属性设置初始化值

struct Fahrenheit {

    var temperature: Double

    var temperature1 = 2

    init() {

        temperature = 32.0

    }

}

var f = Fahrenheit()

print("The default temperature is \(f.temperature)° Fahrenheit")

//2.自定义初始化

//2.1 初始化形式参数

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

struct Color {

    let red, green, blue: Double

    init(red: Double, green: Double, blue: Double) {

        self.red  = red

        self.green = green

        self.blue  = blue

    }

    init(white: Double) {

        red  = white

        green = white

        blue  = white

    }

}

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)

let halfGray = Color(white: 0.5)

//2.4可选属性类型

//如果你的自定义类型有一个逻辑上是允许“无值”的存储属性——大概因为它的值在初始化期间不能被设置,或者因为它在稍后允许设置为“无值”——声明属性为可选类型。

class SurveyQuestion {

    var text: String

    var response: String?

    init(text: String) {

        self.text = text

    }

    func ask() {

        print(text)

    }

}

let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")

cheeseQuestion.ask()

// prints "Do you like cheese?"

cheeseQuestion.response = "Yes, I do like cheese."

//2.5 在初始化中分配常量属性

class SurveyQuestion1 {

    let text: String

    var response: String?

    init(text: String) {

        self.text = text

    }

    func ask() {

        print(text)

    }

}

let beetsQuestion = SurveyQuestion1(text: "How about beets?")

beetsQuestion.ask()

// prints "How about beets?"

//beetsQuestion.text = "change";

beetsQuestion.response = "I also like beets. (But not with cheese.)"

//3.默认初始化器

class ShoppingListItem {

    var name: String?

    var quantity = 1

    var purchased = false

}

var item = ShoppingListItem()

///////////反初始化/////////// deinit

//2.应用反初始化器

class Bank {

    static var coinsInBank = 10_000

    static func distribute(coins numberOfCoinsRequested: Int) -> Int {

        let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)

        coinsInBank -= numberOfCoinsToVend

        return numberOfCoinsToVend

    }

    static func receive(coins: Int) {

        coinsInBank += coins

    }

}

class Player {

    var coinsInPurse: Int

    init(coins: Int) {

        coinsInPurse = Bank.distribute(coins: coins)

    }

    func win(coins: Int) {

        coinsInPurse += Bank.distribute(coins: coins)

    }

    deinit {

        Bank.receive(coins: coinsInPurse)

    }

}

var playerOne: Player? = Player(coins: 100)

print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")

// Prints "A new player has joined the game with 100 coins"

print("There are now \(Bank.coinsInBank) coins left in the bank")

// Prints "There are now 9900 coins left in the bank"

playerOne!.win(coins: 2_000)

print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")

// Prints "PlayerOne won 2000 coins & now has 2100 coins"

print("The bank now only has \(Bank.coinsInBank) coins left")

// Prints "The bank now only has 7900 coins left"

playerOne = nil

print("PlayerOne has left the game")

// prints "PlayerOne has left the game"

print("The bank now has \(Bank.coinsInBank) coins")

// prints "The bank now has 10000 coins"

////////////可选链////////////

//1.可选链代替强制展开

class Person {

    var residence: Residence?

}

class Residence {

    var numberOfRooms = 1

}

let john = Person()

//let roomCount = john.residence!.numberOfRooms

// this triggers a runtime erro

if let roomCount = john.residence?.numberOfRooms {

    print("John's residence has \(roomCount) room(s).")

} else {

    print("Unable to retrieve the number of rooms.")

}

// Prints "Unable to retrieve the number of rooms."

john.residence = Residence()

if let roomCount = john.residence?.numberOfRooms {

    print("John's residence has \(roomCount) room(s).")

} else {

    print("Unable to retrieve the number of rooms.")

}

// Prints "John's residence has 1 room(s)."

////////////错误处理////////////

//1.表示和抛出错误

//2.1使用抛出函数传递错误

enum VendingMachineError: Error {

    case invalidSelection

    case insufficientFunds(coinsNeeded: Int)

    case outOfStock

}

struct Item {

    var price: Int

    var count: Int

}

class VendingMachine {

    var inventory = [

        "Candy Bar": Item(price: 12, count: 7),

        "Chips": Item(price: 10, count: 4),

        "Pretzels": Item(price: 7, count: 11)

    ]

    var coinsDeposited = 0

    func vend(itemNamed name: String) throws {

        guard let item = inventory[name] else {

            throw VendingMachineError.invalidSelection

        }

        guard item.count > 0 else {

            throw VendingMachineError.outOfStock

        }

        guard item.price <= coinsDeposited else {

            throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited)

        }

        coinsDeposited -= item.price

        var newItem = item

        newItem.count -= 1

        inventory[name] = newItem

        print("Dispensing \(name)")

    }

}

let favoriteSnacks = [

    "Alice": "Chips",

    "Bob": "Licorice",

    "Eve": "Pretzels",

]

//由于 vend(itemNamed:) 方法会抛出错误,调用的时候要在前边用 try关键字。

func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws {

    let snackName = favoriteSnacks[person] ?? "Candy Bar"

    try vendingMachine.vend(itemNamed: snackName)

}

// Dispensing Chips

//2.2 使用 Do-Catch 处理错误

//do {

//    try expression

//    statements

//} catch pattern 1 {

//    statements

//} catch pattern 2 where condition {

//    statements

//}

var vendingMachine = VendingMachine()

vendingMachine.coinsDeposited = 8

do {

    try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine)

    // Enjoy delicious snack

} catch VendingMachineError.invalidSelection {

    print("Invalid Selection.")

} catch VendingMachineError.outOfStock {

    print("Out of Stock.")

} catch VendingMachineError.insufficientFunds(let coinsNeeded) {

    print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.")

}

// prints "Insufficient funds. Please insert an additional 2 coins."

//3.指定清理操作 defer

//func processFile(filename: String) throws {

//    if exists(filename) {

//        let file = open(filename)

//        defer {

//            close(file)

//        }

//        while let line = try file.readline() {

//            // Work with the file.

//        }

//        // close(file) is called here, at the end of the scope.

//    }

//}

////////////类型转换//////////// is 和 as

//1.为类型转换定义类层次

class MediaItem {

    var name: String

    init(name: String) {

        self.name = name

    }

}

class Movie: MediaItem {

    var director: String

    init(name: String, director: String) {

        self.director = director

        super.init(name: name)

    }

}

class Song: MediaItem {

    var artist: String

    init(name: String, artist: String) {

        self.artist = artist

        super.init(name: name)

    }

}

let library = [

    Movie(name: "Casablanca", director: "Michael Curtiz"),

    Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),

    Movie(name: "Citizen Kane", director: "Orson Welles"),

    Song(name: "The One And Only", artist: "Chesney Hawkes"),

    Song(name: "Never Gonna Give You Up", artist: "Rick Astley")

]

// "library" 的类型被推断为[MediaItem]

//2.类型检查

var movieCount = 0

var songCount = 0

for item in library {

    if item is Movie {

        movieCount += 1

    } else if item is Song {

        songCount += 1

    }

}

print("Media library contains \(movieCount) movies and \(songCount) songs")

// Prints "Media library contains 2 movies and 3 songs"

//3.向下类型转换

//如果你不确定你向下转换类型是否能够成功,请使用条件形式的类型转换操作符 ( as? )。使用条件形式的类型转换操作符总是返回一个可选项,如果向下转换失败,可选值为 nil 。这允许你检查向下类型转换是否成功。

for item in library {

    if let movie = item as? Movie {

        print("Movie: '\(movie.name)', dir. \(movie.director)")

    } else if let song = item as? Song {

        print("Song: '\(song.name)', by \(song.artist)")

    }

}

// Movie: 'Casablanca', dir. Michael Curtiz

// Song: 'Blue Suede Shoes', by Elvis Presley

// Movie: 'Citizen Kane', dir. Orson Welles

// Song: 'The One And Only', by Chesney Hawkes

// Song: 'Never Gonna Give You Up', by Rick Astley

//当你确信向下转换类型会成功时,使用强制形式的类型转换操作符( as! )。当你向下转换至一个错误的类型时,强制形式的类型转换操作符会触发一个运行错误。

//4\. Any 和 AnyObject 的类型转换

var things = [Any]()

things.append(0)

things.append(0.0)

things.append(42)

things.append(3.14159)

things.append("hello")

things.append((3.0, 5.0))

things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))

things.append({ (name: String) -> String in "Hello, \(name)" })

for thing in things {

    switch thing {

    case 0 as Int:

        print("zero as an Int")

    case 0 as Double:

        print("zero as a Double")

    case let someInt as Int:

        print("an integer value of \(someInt)")

    case let someDouble as Double where someDouble > 0:

        print("a positive double value of \(someDouble)")

    case is Double:

        print("some other double value that I don't want to print")

    case let someString as String:

        print("a string value of \"\(someString)\"")

    case let (x, y) as (Double, Double):

        print("an (x, y) point at \(x), \(y)")

    case let movie as Movie:

        print("a movie called \(movie.name), dir. \(movie.director)")

    case let stringConverter as (String) -> String:

        print(stringConverter("Michael"))

    default:

        print("something else")

    }

}

// zero as an Int

// zero as a Double

// an integer value of 42

// a positive double value of 3.14159

// a string value of "hello"

// an (x, y) point at 3.0, 5.0

// a movie called Ghostbusters, dir. Ivan Reitman

// Hello, Michael

let optionalNumber: Int? = 3

things.append(optionalNumber)        // Warning

things.append(optionalNumber as Any) // No warning

///////////内嵌类型///////////

struct BlackjackCard {

    // nested Suit enumeration

    enum Suit: Character {

        case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣"

    }

    // nested Rank enumeration

    enum Rank: Int {

        case two = 2, three, four, five, six, seven, eight, nine, ten

        case jack, queen, king, ace

        struct Values {

            let first: Int, second: Int?

        }

        var values: Values {

            switch self {

            case .ace:

                return Values(first: 1, second: 11)

            case .jack, .queen, .king:

                return Values(first: 10, second: nil)

            default:

                return Values(first: self.rawValue, second: nil)

            }

        }

    }

    // BlackjackCard properties and methods

    let rank: Rank, suit: Suit

    var description: String {

        var output = "suit is \(suit.rawValue),"

        output += " value is \(rank.values.first)"

        if let second = rank.values.second {

            output += " or \(second)"

        }

        return output

    }

}

let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades)

print("theAceOfSpades: \(theAceOfSpades.description)")

// Prints "theAceOfSpades: suit is ♠, value is 1 or 11"

////////////扩展////////////

//2.计算属性

extension Double {

    var km: Double { return self * 1_000.0 }

    var m: Double { return self }

    var cm: Double { return self / 100.0 }

    var mm: Double { return self / 1_000.0 }

    var ft: Double { return self / 3.28084 }

}

let oneInch = 25.4.mm

print("One inch is \(oneInch) meters")

// Prints "One inch is 0.0254 meters"

let threeFeet = 3.ft

print("Three feet is \(threeFeet) meters")

// Prints "Three feet is 0.914399970739201 meters"

let aMarathon = 42.km + 195.m

print("A marathon is \(aMarathon) meters long")

// Prints "A marathon is 42195.0 meters long"

//3.初始化器

struct Size4 {

    var width = 0.0, height = 0.0

}

struct Point4 {

    var x = 0.0, y = 0.0

}

struct Rect4 {

    var origin = Point4()

    var size = Size4()

}

let defaultRect = Rect4()

let memberwiseRect = Rect4(origin: Point4(x: 2.0, y: 2.0),

                          size: Size4(width: 5.0, height: 5.0))

extension Rect4 {

    init(center: Point4, size: Size4) {

        let originX = center.x - (size.width / 2)

        let originY = center.y - (size.height / 2)

        self.init(origin: Point4(x: originX, y: originY), size: size)

    }

}

let centerRect = Rect4(center: Point4(x: 4.0, y: 4.0),

                      size: Size4(width: 3.0, height: 3.0))

// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)

//4.方法

extension Int {

    func repetitions(task: () -> Void) {

        for _ in 0..<self {

            task()

        }

    }

}

3.repetitions {

    print("Hello!")

}

// Hello!

// Hello!

// Hello!

//4.1异变实例方法

extension Int {

    mutating func square() {

        self = self * self

    }

}

someInt = 3

someInt.square()

// someInt is now 9

//5.下标

extension Int {

    subscript(digitIndex: Int) -> Int {

        var decimalBase = 1

        for _ in 0..<digitIndex {

            decimalBase *= 10

        }

        return (self / decimalBase) % 10

    }

}

746381295[0]

// returns 5

746381295[1]

// returns 9

746381295[2]

// returns 2

746381295[8]

// returns 7

//6.内嵌类型

extension Int {

    enum Kind {

        case negative, zero, positive

    }

    var kind: Kind {

        switch self {

        case 0:

            return .zero

        case let x where x > 0:

            return .positive

        default:

            return .negative

        }

    }

}

func printIntegerKinds(_ numbers: [Int]) {

    for number in numbers {

        switch number.kind {

        case .negative:

            print("- ", terminator: "")

        case .zero:

            print("0 ", terminator: "")

        case .positive:

            print("+ ", terminator: "")

        }

    }

    print("")

}

printIntegerKinds([3, 19, -27, 0, -6, 0, 7])

// Prints "+ + - 0 - 0 + "

///////////协议///////////

//1.协议的语法

protocol SomeProtocol {

    // protocol definition goes here

}

//struct SomeStructure: FirstProtocol, AnotherProtocol {

//    // structure definition goes here

//}

//

//class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {

//    // class definition goes here

//}

//2.属性要求

//协议同时要求一个属性必须明确是可读的或可读的和可写的。

protocol SomeProtocol1 {

    var mustBeSettable: Int { get set }

    var doesNotNeedToBeSettable: Int { get }

}

protocol FullyNamed {

    var fullName: String { get }

}

struct Person1: FullyNamed {

    var fullName: String

}

let john1 = Person1(fullName: "John Appleseed")

print("fullName \(john1.fullName)")

// john.fullName is "John Appleseed"

class Starship: FullyNamed {

    var prefix: String?

    var name: String

    init(name: String, prefix: String? = nil) {

        self.name = name

        self.prefix = prefix

    }

    var fullName: String {

        return (prefix != nil ? prefix! + " " : "") + name

    }

}

var ncc1701 = Starship(name: "Enterprise", prefix: "USS")

// ncc1701.fullName is "USS Enterprise"

//3.方法要求

protocol RandomNumberGenerator {

    func random() -> Double

}

class LinearCongruentialGenerator: RandomNumberGenerator {

    var lastRandom = 42.0

    let m = 139968.0

    let a = 3877.0

    let c = 29573.0

    func random() -> Double {

        lastRandom = ((lastRandom * a + c).truncatingRemainder(dividingBy:m))

        return lastRandom / m

    }

}

let generator = LinearCongruentialGenerator()

print("Here's a random number: \(generator.random())")

// Prints "Here's a random number: 0.37464991998171"

print("And another one: \(generator.random())")

// Prints "And another one: 0.729023776863283"

//4.异变方法要求

protocol Togglable {

    mutating func toggle()

}

enum OnOffSwitch: Togglable {

    case off, on

    mutating func toggle() {

        switch self {

        case .off:

            self = .on

        case .on:

            self = .off

        }

    }

}

var lightSwitch = OnOffSwitch.off

lightSwitch.toggle()

// lightSwitch is now equal to .on

//6.将协议作为类型

//class Dice {

//    let sides: Int

//    let generator: RandomNumberGenerator

//    init(sides: Int, generator: RandomNumberGenerator) {

//        self.sides = sides

//        self.generator = generator

//    }

//    func roll() -> Int {

//        return Int(generator.random() * Double(sides)) + 1

//    }

//}

//

//var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator())

//for _ in 1...5 {

//    print("Random dice roll is \(d6.roll())")

//}

//// Random dice roll is 3

//// Random dice roll is 5

//// Random dice roll is 4

//// Random dice roll is 5

//// Random dice roll is 4

///////////泛型///////////

//2.泛型函数

//old

func swapTwoDoubles(_ a: inout Double, _ b: inout Double) {

    let temporaryA = a

    a = b

    b = temporaryA

}

//new

func swapTwoValues<T>(_ a: inout T, _ b: inout T) {

    let temporaryA = a

    a = b

    b = temporaryA

}

var someString = "hello"

var anotherString = "world"

swapTwoValues(&someString, &anotherString)

////////////////////////////////////////////////////

/////////////自动引用计数/////////////

//ARC

class Person1 {

    let name: String

    init(name: String) {

        self.name = name

        print("\(name) is being initialized")

    }

    deinit {

//        print("\(name) is being deinitialized")

    }

}

var reference1: Person1?

var reference2: Person1?

var reference3: Person1?

reference1 = Person1(name: "John Appleseed")

reference2 = reference1

reference3 = reference1

reference1 = nil

reference2 = nil

reference3 = nil

//3.类实例之间的循环强引用

//class Person {

//    let name: String

//    init(name: String) { [self.name](http://self.name/) = name }

//    var apartment: Apartment?

//    deinit { print("\(name) is being deinitialized") }

//}

//

//class Apartment {

//    let unit: String

//    init(unit: String) { self.unit = unit }

//    var tenant: Person?

//    deinit { print("Apartment \(unit) is being deinitialized") }

//}

//var john: Person?

//var unit4A: Apartment?

//john = Person(name: "John Appleseed")

//unit4A = Apartment(unit: "4A")

//john!.apartment = unit4A

//unit4A!.tenant = john

//john = nil

//unit4A = nil

//循环引用了,无法释放资源,内存泄漏了

//4 解决实例之间的循环强引用

//4.1弱引用    ARC 给弱引用设置 nil 时不会调用属性观察者。

//class Person {

//    let name: String

//    init(name: String) { [self.name](http://self.name/) = name }

//    var apartment: Apartment?

//    deinit { print("\(name) is being deinitialized") }

//}

//

//class Apartment {

//    let unit: String

//    init(unit: String) { self.unit = unit }

//    weak var tenant: Person?

//    deinit { print("Apartment \(unit) is being deinitialized") }

//}

//var john: Person?

//var unit4A: Apartment?

//

//john = Person(name: "John Appleseed")

//unit4A = Apartment(unit: "4A")

//

//john!.apartment = unit4A

//unit4A!.tenant = john

//john = nil

//// prints "John Appleseed is being deinitialized"

//unit4A = nil

//// prints "Apartment 4A is being deinitialized"

//

////4.2无主引用

////和弱引用类似,无主引用不会牢牢保持住引用的实例。但是不像弱引用,总之,无主引用假定是永远有值的。因此,无主引用总是被定义为非可选类型。你可以在声明属性或者变量时,在前面加上关键字 unowned 表示这是一个无主引用。

//class Customer {

//    let name: String

//    var card: CreditCard?

//    init(name: String) {

//        [self.name](http://self.name/) = name

//    }

//    deinit { print("\(name) is being deinitialized") }

//}

//

//class CreditCard {

//    let number: UInt64

//    unowned let customer: Customer

//    init(number: UInt64, customer: Customer) {

//        self.number = number

//        self.customer = customer

//    }

//    deinit { print("Card #\(number) is being deinitialized") }

//}

//

//var john: Customer?

//john = Customer(name: "John Appleseed")

//john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

//john = nil

//// prints "John Appleseed is being deinitialized"

//// prints "Card #1234567890123456 is being deinitialized"

//5.闭包的循环强引用

//尽管闭包多次引用了 self ,它只捕获 HTMLElement 实例的一个强引用。

//class HTMLElement {

//

//    let name: String

//    let text: String?

//

//    lazy var asHTML: () -> String = {

//        if let text = self.text {

//            return "<\(self.name)>\(text)</\(self.name)>"

//        } else {

//            return "<\(self.name) />"

//        }

//    }

//

//    init(name: String, text: String? = nil) {

//        [self.name](http://self.name/) = name

//        self.text = text

//    }

//

//    deinit {

//        print("\(name) is being deinitialized")

//    }

//

//}

//

//let heading = HTMLElement(name: "h1", text: "some default text")

//print(heading.asHTML())

////prints <h1>some default text</h1>

////heading = nil

//

//var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")

//print(paragraph!.asHTML())

//// prints"hello, world"

//paragraph = nil

////不会触发 being deinitialized

//6\. 解决闭包的循环强引用

//6.1 定义捕获列表

//lazy var someClosure: (Int, String) -> String = {

//    [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in

//    // closure body goes here

//}

//

//lazy var someClosure: () -> String = {

//    [unowned self, weak delegate = self.delegate!] in

//    // closure body goes here

//}

//6.2 弱引用和无主引用

//如果被捕获的引用永远不会变为 nil ,应该用无主引用而不是弱引用。

class HTMLElement {

    let name: String

    let text: String?

    lazy var asHTML: () -> String = {

        [unowned self] in

        if let text = self.text {

            return "<\(self.name)>\(text)</\(self.name)>"

        } else {

            return "<\(self.name) />"

        }

    }

    init(name: String, text: String? = nil) {

        self.name = name

        self.text = text

    }

    deinit {

        print("\(name) is being deinitialized")

    }

}

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")

print(paragraph!.asHTML())

// prints "<p>hello, world</p>"

paragraph = nil

// prints "p is being deinitialized"
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容