//: 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..()
print("letters is of type Set with \(letters.count) items.")
// prints "letters is of type Set 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
var favoriteGenres: Set = ["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.. 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.. 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.. 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.. Int {
var decimalBase = 1
for _ in 0.. 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(_ 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 some default text
////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 "hello, world
"
paragraph = nil
// prints "p is being deinitialized"