Last active
September 16, 2016 15:55
-
-
Save colourful987/148d367f2c4f84f8fe9b30e0441d8f90 to your computer and use it in GitHub Desktop.
Seven Demo For Explaining Swift Closures Capture Semantics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: Playground - noun: a place where people can play | |
import UIKit | |
import PlaygroundSupport | |
PlaygroundPage.current.needsIndefiniteExecution = true | |
class Pokemon :CustomStringConvertible{ | |
let name: String | |
init(name:String) { | |
self.name = name | |
} | |
var description:String{return "<Pokemon \(name)>"} | |
deinit { | |
print("\(self) escaped") | |
} | |
} | |
func delay(seconds: Int, closure: @escaping ()->()) { | |
let time = DispatchTime.now() + .seconds(seconds) | |
DispatchQueue.main.asyncAfter(deadline: time) { | |
print("🕑") | |
closure() | |
} | |
} | |
//: 关于GCD的知识,请点击[这里](http://www.jianshu.com/p/8cb4f395d2c4) | |
func demo1() { | |
let pokemon = Pokemon(name: "Mewtwo") | |
print("before closure: \(pokemon)") | |
delay(seconds: 1) {// 由于delay函数使用了异步方式 所以不会阻塞当前线程 而是立即执行之后的print bye | |
print("inside closure: \(pokemon)") | |
} | |
print("bye") | |
} | |
func demo2() { | |
var pokemon = Pokemon(name: "Pikachu") | |
print("before closure: \(pokemon)") // 1.目前皮卡丘 | |
delay(seconds: 1) { | |
print("inside closure: \(pokemon)") // 4. 闭包拥有的是pokemon 指针 而不是内容 | |
} | |
pokemon = Pokemon(name: "Mewtwo") // 2.精灵球捕获了超梦 却让皮卡丘释放了 | |
print("after closure: \(pokemon)")// 3.此时精灵球里是超梦 | |
} | |
func demo3() { | |
var value = 42 | |
print("before closure: \(value)") | |
delay(seconds: 1) { | |
print("inside closure: \(value)") | |
} | |
value = 1337 | |
print("after closure: \(value)") | |
} | |
func demo4() { | |
var value = 42 | |
print("before closure: \(value)") | |
delay(seconds: 1) { | |
print("inside closure 1, before change: \(value)") | |
value = 1337 | |
print("inside closure 1, after change: \(value)") | |
} | |
delay(seconds: 2) { | |
print("inside closure 2: \(value)") | |
} | |
} | |
func demo5() { | |
var value = 42 | |
print("before closure: \(value)") | |
delay(seconds: 1) { [constValue = value] in | |
print("inside closure: \(constValue)") | |
} | |
value = 1337 | |
print("after closure: \(value)") | |
} | |
func demo6() { | |
var pokemon = Pokemon(name: "Pikachu") | |
print("before closure: \(pokemon)") | |
delay(seconds: 1) { [pokemonCopy = pokemon] in | |
print("inside closure: \(pokemonCopy)") | |
} | |
pokemon = Pokemon(name: "Mewtwo") | |
print("after closure: \(pokemon)") | |
} | |
func demo6_equivalent() { | |
var pokemon = Pokemon(name: "Pikachu") | |
print("before closure: \(pokemon)") | |
// here we create an intermediate variable to hold the instance | |
// pointed by the variable at that point in the code: | |
let pokemonCopy = pokemon | |
delay(seconds: 1) { | |
print("inside closure: \(pokemonCopy)") | |
} | |
pokemon = Pokemon(name: "Mewtwo") | |
print("after closure: \(pokemon)") | |
} | |
func demo7() { | |
var pokemon = Pokemon(name: "Mew") | |
print("➡️ Initial pokemon is \(pokemon)") | |
delay(seconds: 1) { [capturedPokemon = pokemon] in | |
print("closure 1 — pokemon captured at creation time: \(capturedPokemon)") | |
print("closure 1 — variable evaluated at execution time: \(pokemon)") | |
pokemon = Pokemon(name: "Pikachu") | |
print("closure 1 - pokemon has been now set to \(pokemon)") | |
} | |
pokemon = Pokemon(name: "Mewtwo") | |
print("🔄 pokemon changed to \(pokemon)") | |
delay(seconds: 2) { [capturedPokemon = pokemon] in | |
print("closure 2 — pokemon captured at creation time: \(capturedPokemon)") | |
print("closure 2 — variable evaluated at execution time: \(pokemon)") | |
pokemon = Pokemon(name: "Charizard") | |
print("closure 2 - value has been now set to \(pokemon)") | |
} | |
} | |
// execute 例子想要说明的问题是 函数结束了 临时变量 pokemon 应该释放掉 实际不是的 因为我们的闭包对它有个retain操作 | |
//demo1() | |
// 学习 Swift 在闭包执行时才会取出捕获变量的值 我们可以认为它之前捕获的是变量的引用 | |
//demo2() | |
// 虽然是值类型 但是!还是引用 | |
//demo3() | |
// 了解变量可以在闭包内修改 | |
//demo4() | |
// 如果是在闭包创建时捕获 那么值copy 而不是引用 | |
//demo5() | |
// demo5 是值类型创建闭包时copy 那么一个类呢? | |
//demo6() | |
//demo6_equivalent() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment