Array of capturing quick close by reference
In Swift Collections, defaults are passed in by default, and we can user inout
get it passed by reference in the function arguments, but how can we do that in the capturing variables of the closure?
var list = [1, 2, 3]
func edit(inout list: [Int]) {
list.append(4)
dispatch_async(dispatch_get_main_queue()) {
list.append(5)
}
}
edit(&list)
...// after dispatch_async was executed
NSLog("\(list)")
The result will be [1, 2, 3, 4]
How do I change the original variable () inside a closure?
UPDATE:
Actually I have a workaround to handle this case by putting an array into an object so that I can pass that object to a function by reference and we can modify the same instance of the array inside the function. but I want to see any clever way of archiving this
source to share
To get the escape variable from a closure, you need @escaping
to check this . A workaround is to put the completion function as an argument and not in a variable inout
.
class MyClass {
static func edit(_ list: [Int], _ completion: @escaping ([Int]) -> ()) {
var list = list
list.append(4)
DispatchQueue.main.async() {
list.append(5)
completion(list)
}
}
}
var myList = [1, 2, 3]
MyClass.edit(myList) { (list) in
myList = list
print("My list after editing: \(myList)")
}
print("My list without editing: \(myList)")
Note : The above example is for Swift 3 where parameters are inout
not allowed to be captured in the closure. Based on your posts, you can use a lower version of the Swift, which you could use inout
instead of setting up a volatile list: var list = list
. However, the logic is very similar.
For more information, check the Restrict Capture to Context @noescape checkbox in Swift Evolution:
The fast behavior of closures taking over parameters
inout
and leaving their surrounding context is a common source of confusion. We must disallow implicit capture of parametersinout
, except for@noescape
closures.
source to share