异步函数调用与无主对象的取消初始化冲突
Asynchronous function call conflicts with deinitialization of an unowned object
我有类似的代码,与异步上下文中的事件处理相关:
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
永远不应该一个问题。
但是,我从 Foo.bar()
内部的 self.b
访问中得到这个错误(运行 在一些 GCD 队列上,不是主队列):
exc_breakpoint (code=exc_i386_bpt subcode=0x0)
调试器显示 self.b
完全没问题:不是零,所有值都应该是。
但是,调试器也显示,与此同时,主线程正忙于deinitializing对应的B
;它在 <... *>
中暂停,即在可以从 a
中删除对 foo
的引用之前。所以对我来说 self.b
在这个时间点是一个不好的参考是有道理的。
这似乎是一个不幸的时机——但我怎样才能消除这种潜在的崩溃呢?毕竟,我无法阻止对 bar()
的异步调用!
基本上,我们在这里打破了 unowned
的先决条件:即使调试器没有显示它,Foo.b
可以 变成 nil
在 Foo
的生命周期中。当我们声称(通过使用 unowned
)它不能时,编译器相信了我们,所以我们崩溃了。
似乎有两条出路。
确保 Foo.b
是最后一个对 Foo
的相应实例拥有强引用的对象。然后,应分别删除这两个对象 "together"。在 Foo.b
被取消初始化(或之后)时,无法调用 Foo.bar()
。
使 Foo.b
成为弱引用,即将其声明为 weak var b: B?
。这让代码变得更乱,但至少可以让它变得安全。
我有类似的代码,与异步上下文中的事件处理相关:
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
永远不应该一个问题。
但是,我从 Foo.bar()
内部的 self.b
访问中得到这个错误(运行 在一些 GCD 队列上,不是主队列):
exc_breakpoint (code=exc_i386_bpt subcode=0x0)
调试器显示 self.b
完全没问题:不是零,所有值都应该是。
但是,调试器也显示,与此同时,主线程正忙于deinitializing对应的B
;它在 <... *>
中暂停,即在可以从 a
中删除对 foo
的引用之前。所以对我来说 self.b
在这个时间点是一个不好的参考是有道理的。
这似乎是一个不幸的时机——但我怎样才能消除这种潜在的崩溃呢?毕竟,我无法阻止对 bar()
的异步调用!
基本上,我们在这里打破了 unowned
的先决条件:即使调试器没有显示它,Foo.b
可以 变成 nil
在 Foo
的生命周期中。当我们声称(通过使用 unowned
)它不能时,编译器相信了我们,所以我们崩溃了。
似乎有两条出路。
确保
Foo.b
是最后一个对Foo
的相应实例拥有强引用的对象。然后,应分别删除这两个对象 "together"。在Foo.b
被取消初始化(或之后)时,无法调用Foo.bar()
。使
Foo.b
成为弱引用,即将其声明为weak var b: B?
。这让代码变得更乱,但至少可以让它变得安全。