Swift Closure
Documents Apple References Blog Blog What is closure? Closures are self-contained blocks of functinality that can be PASSED around and USED in your code -> Closure is a 1st class Object Closures can CAPTURE and STORE REFERENCES to any constants and variables from the ...
Documents
- Apple References
- Blog
- Blog
What is closure?
Closures are self-contained blocks of functinality that can be PASSED around and USED in your code
-> Closure is a 1st class Object
Closures can CAPTURE and STORE REFERENCES to any constants and variables from the CONTEXT which they ayre defined
-> by reference mean not value, means, If we change any thing inside the closure, the object outsite the closure will also be affected
Closures are Reference Types
-> If I assign a cloure to two var, they actually refer to the same closure
Escape vs Non-Escaping
escape: mean the close will be STORED somewhere to execute later (and of course, its context also being STORED and this is the main reason cause retain cycles). Usually meet as api call
DispatchQueue.main.async { ... }
non-escape: the close will be execute and return immediately, not being store, this is the trivia case. Usually meet when use a function in a collection:
[1,2,3].forEach { number in ... }
If a closure is a property, It's auto escaping
// declare a callback being call a user is picked var onUserPick: ((_ user: User) -> Void)?
Capture Values
- Values are capture when being ACCESS (RUN)
var value = 1 let checkValue = { () -> Void in print("value in closure: (value)") // 2, not 1, because we change value before call value = 3 // change to three } value = 2 // change value affect in closure because I don't pass it in captures list print("value before closure: (value)") // 2: trivia, value has been changed checkValue() print("value after closure: (value)") // 3: value is updated inside the closure
So the whole life cycle of value: 1 -> 2 -> 3
- If using captures list the values are capture/copy when being PASSED (DEFINITION)
var value = 1 let checkValue = { [copyOfValue = value] () -> Void in print("value in closure: (copyOfValue)") // 1: because it has been copy at passing time // copyOfValue = 3 // cannot change value of parameter } value = 2 // change value is NOT affect in closure, because I used captures list print("value before closure: (value)") // 2: trivia, value has been changed checkValue() print("value after closure: (value)") // 2: pass by value, not effect in closure
So the whole life cycle of value: 1 -> 1(copied) -> 2 -> 2
- If the value is an Object, value is always pass by references whethe using captures list or not because object always a pointer
var user = User(name: "Kenji") let checkValue = { [copyOfUser = user] () -> Void in print("value in closure (copyOfUser.name)"); // Shinja copyOfUser.name = "Otomo" // can change the props of object } user.name = "Shinja" print("value before call closure (user.name)") // Shinja checkValue(); print("value after after call closure (user.name)") // Otomo
Trailing Closure
Just a convenient way to write closure when it is the last argument in a function. When call that function, you can open parenthesis at the end (that why it is called trailing)
// define func foo(closure: () -> Void) { ... foo body } // calling foo(closure: { ... closure body });