我有类似的代码,与异步上下文中的事件处理有关:
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() { <... #> }
}
}
我认为这应该是安全的代码:在一个实例b
消失之前,它会清除对其的所有引用foo
,因此引用Foo.b
永远不会成为问题。
self.b
但是,我从内部的访问中得到这个错误Foo.bar()
(在一些 GCD 队列上运行,而不是在主队列上运行):
exc_breakpoint(代码=exc_i386_bpt 子代码=0x0)
调试器显示这self.b
完全没问题:不是零,所有值都是应有的。
但是,调试器也显示,与此同时,主线程正忙于去初始化相应的B
; 它在 中暂停<... *>
,即在foo
可以从 中删除对 的引用之前a
。self.b
所以对我来说,在这个时候这将是一个不好的参考是有道理的。
这似乎是一个不幸的时机——但我怎样才能消除这种崩溃的可能性呢?bar()
毕竟,我无法阻止异步调用的发生!