I have code similar to this, related to event handling in an asynchronous context:
class A {
var foos: Set<Fooable>
}
protocol Fooable {
func bar()
}
class B {
var a: A
var foo: Foo!
init(a: A) {
self.a = a
}
func start() {
self.foo = Foo(self)
self.a.foos.insert(self.foo)
}
deinit {
<... *>
if self.foo != nil {
self.a.remove(self.foo)
}
}
class Foo: Fooable {
unowned let b: B
init(_ b: B) {
self.b = B
}
func bar() { <... #> }
}
}
I figured that this should be safe code: before an instance of b
is gone, it cleans up all references to its foo
, so the reference Foo.b
should never be an issue.
However, I get this error from an access of self.b
inside of Foo.bar()
(run on some GCD queue, not main):
exc_breakpoint (code=exc_i386_bpt subcode=0x0)
The debugger shows that self.b
is completely fine: not nil, all values are as they should be.
However, the debugger also shows that, at the same time, the main thread is busy deinitializing the corresponding B
; it's paused in <... *>
, i.e. before the reference to foo
could be removed from a
. So it makes sense to me that self.b
would be a bad reference at this point in time.
This seems to be unfortunate timing -- but how can I do away with this crash potential? I can not prevent asynchronous calls to bar()
from happening, after all!