Question: For the case of ()
-return closures, is there any way to access a variable that ARC lets live only due to a single strong reference from a closure closing over it? In the example below: accessing bb
in the closure.
Below follows an example to show what I mean.
In the Language Reference - Expressions, it reads
Capture Lists
By default, a closure expression captures constants and variables from its surrounding scope with strong references to those values. You can use a capture list to explicitly control how values are captured in a closure.
...
Consider the following example, using a weak and a strong capture of two class type instances
class MyClass {
var myInt : Int = 0
func printMyInt() {
print(myInt)
}
}
func getClosure(a: MyClass, _ b: MyClass) -> (() -> ()) {
return { [weak aa = a, bb = b] in
aa?.printMyInt() ?? print("Lost reference")
bb.printMyInt()
}
}
func foo() -> (() -> ()) {
let a = MyClass()
let b = MyClass()
let closure = getClosure(a, b)
closure() // 0, 0
a.myInt = 1
b.myInt = 2
closure() // 1, 2
return closure
}
If foo()
is called, then at the return of closure
, MyClass
instances a
and b
are out of scope. In the closure itself, aa
keeps a weak reference to a
, so a
(memory) will be "destroyed" by ARC, and aa
will become nil.
However, since the closure closes over b
with a strong reference, ARC will retain the memory for b
until the closure itself goes out of scope.
let closure = foo()
closure() // Lost reference, 2 <-- OK, expected
/* 'b' (not the reference, but the object in memory) still lives, but
cant be explicitly accessed? */
Hence my question: how to access, in this case, bb
within the closure.
What I've tried
I've tried without success using Mirror
:
var bar = Mirror(reflecting: closure)
print(bar.children.count) // 0
Also, I know we can "access" bb
in the example above by adding a return type (MyClass
) to the closure, but I'm wondering if we can actually access it without such a workaround (hence the ()
-return specific closure in the question above).
Where I've looked prior to posting this question
I've been searching around SO for a possible existing threads that asks and answers this question, but the closest one I found,
don't really answer my question here. (Or perhaps the workarounds in the answers to that question does, and the answer to my question above is "you can't"?)