Let's say changing the inout in async-callback is pointless.
From an official document :
Parameters can provide default values ββto simplify function calls, and can be passed as input parameters that modify the passed variable after it completes .
...
The in-out parameter has a value that is passed to the function, changed by the function, and passed back from the function to replace the original value.
Semantically, the in-out parameter is not "call-by-reference" , but "call by copy, restore . "
In your case, counter is only supported when returning getOneUserApiData() , and not in the dataTaskWithRequest() .
Here is what happened in your code
- when
getOneUserApiData() called, counter 0 copied to c 1 - circuit locks
c 1 - call
dataTaskWithRequest() getOneUserApiData returned, and the value is unmodified - c 1 is written with feedback to counter- repetition procedure 1-4 for
c 2 , c 3 , c 4 ... - ... extract from the Internet ...
- callback is called and increments
c 1 . - callback is called and increments
c 2 . - callback is called and increments
c 3 . - callback is called and increments
c 4 . - ...
As a result, counter modified: (
Detailed explanation
Usually the in-out parameter is passed by reference, but this is simply the result of compiler optimization. When a closure captures the inout , "pass-by-reference" is not safe because the compiler cannot guarantee the lifetime of the original value. For example, consider the following code:
func foo() -> () -> Void { var i = 0 return bar(&i) } func bar(inout x:Int) -> () -> Void { return { x++ return } } let closure = foo() closure()
In this code, var i freed when foo() returned. If x is a reference to i , x++ causes an access violation. To prevent this race condition, Swift adopts a challenge-copy-restore strategy here.
rintaro
source share