ARC正在取消仍然具有活动引用的协议对象,这是一个错误还是预期的行为,以及解决方法是什么?
protocol SomeProtocol: class {
...
}
class SomeClass: SomeProtocol {
...
}
class ClassA {
var protocolObject: SomeProtocol!
...
}
class ClassB {
var x: SomeClass!
func f() {
self.x = SomeClass()
var objA = ClassA()
objA.protocolObject = self.x
}
}
在此示例中,当objA被取消初始化时,它会尝试取消初始化objA.protocolObject,即使仍有一个活动的引用为objB.x.这会导致运行时错误EXC_BAD_ACCESS。但是,如果ClassA定义如下:
class ClassA {
var protocolObject: SomeClass
}
代码运行时没有错误,协议对象未被取消初始化。有什么想法吗?
答案 0 :(得分:1)
<强>更新强>
从iOS8.0开始,此错误似乎已得到解决。
我遇到了同样的问题,并且已经缩小到被定义为仅限类协议的协议的问题(即protocol XXX: class
)。
protocol FooProtocol {
var name: String { get }
}
// Note: Class-Only protocol
protocol BarProtocol: class {
var name: String { get }
}
class Foo: FooProtocol {
let name: String = "Foo"
deinit {
println("\(name) deinit")
}
}
class Bar: BarProtocol {
let name: String = "Bar"
deinit {
println("\(name) deinit")
}
}
class Container {
let foo: FooProtocol = Foo()
let bar: BarProtocol = Bar()
}
class ViewController: UIViewController {
let container = Container()
override func viewDidLoad() {
super.viewDidLoad()
// Prints 'Test: Foo'
test(container.foo)
// Prints 'Test: Bar', followed by 'Bar deinit'
// subsequent access to the `bar` variable results in a crash
test(container.bar)
}
func test(bar: BarProtocol) {
println("Test: \(bar.name)")
}
func test(foo: FooProtocol) {
println("Test: \(foo.name)")
}
}
目前的解决方法是放弃使用仅限类协议。我已经向Apple提交了一份错误报告,rdar:// 18287447。