Swift 异步函数调用与无主对象的去初始化冲突
我有类似的代码,与异步上下文中的事件处理相关:Swift 异步函数调用与无主对象的去初始化冲突,swift,concurrency,automatic-ref-counting,deinit,Swift,Concurrency,Automatic Ref Counting,Deinit,我有类似的代码,与异步上下文中的事件处理相关: 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) se
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() { <... #> }
}
}
A类{
var-foos:Set
}
协议可食{
func bar()
}
B类{
变量a:a
福娃:福娃!
初始(a:a){
self.a=a
}
func start(){
self.foo=foo(self)
self.a.foos.insert(self.foo)
}
脱硝{
如果self.foo!=nil{
self.a.remove(self.foo)
}
}
Foo类:可食{
无主出租
初始化(b:b){
self.b=b
}
func bar(){}
}
}
我认为这应该是安全的代码:在b
的实例消失之前,它会清除对其foo
的所有引用,因此引用foo.b
应该永远不会成为问题
但是,我从Foo.bar()
内部的self.b
访问中获得此错误(在某些GCD队列上运行,而不是在主队列上运行):
exc_断点(代码=exc_i386_bpt子代码=0x0)
调试器显示,self.b
是完全正确的:不是零,所有值都是应该的
但是,调试器还显示,与此同时,主线程正忙于取消初始化相应的B
;它在
中暂停,即在a
中删除对foo
的引用之前。因此,对我来说,self.b
在这个时候将是一个不好的参考
这似乎是一个不幸的时机——但我怎样才能消除这种崩溃的可能性呢?毕竟,我无法阻止对
bar()
的异步调用发生 基本上,我们在这里打破了无主
的先决条件:即使调试器没有显示它,Foo.b
在Foo
的生命周期内也可以变成nil
。当我们声称(使用无主)它不能时,编译器相信了我们,所以我们崩溃了
似乎有两条出路
确保Foo.b
是保存对Foo
的各个实例的强引用的最后一个对象。然后,两个物体应分别“一起”移除。当Foo.b
被取消初始化时(或之后),不可能调用Foo.bar()
使Foo.b
成为弱引用,即将其声明为弱变量b:b?
。这使得代码更加混乱,但至少可以保证安全