Memory management Swift协议对象弧
ARC正在取消初始化仍有活动引用的协议对象,这是一个错误还是预期的行为,解决方法是什么Memory management Swift协议对象弧,memory-management,swift,automatic-ref-counting,protocols,Memory Management,Swift,Automatic Ref Counting,Protocols,ARC正在取消初始化仍有活动引用的协议对象,这是一个错误还是预期的行为,解决方法是什么 protocol SomeProtocol: class { ... } class SomeClass: SomeProtocol { ... } class ClassA { var protocolObject: SomeProtocol! ... } class ClassB { var x: SomeClass! func f() {
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_访问。但是,如果ClassA的定义如下:
class ClassA {
var protocolObject: SomeClass
}
代码运行时没有错误,并且protocolObject没有被取消初始化。有什么想法吗?更新 从iOS8.0开始,此错误似乎已得到解决
我遇到了同样的问题,并将问题缩小到协议被定义为仅类协议(即
协议XXX:Class
)
当前的解决方法是放弃使用仅类协议。我已经向苹果公司提交了一份缺陷报告,rdar://18287447.您正在运行什么测试版?该示例在b7中对我来说没有问题。
ClassA
实例在从b.f()
返回后立即被取消初始化,但在此之后,我可以随时调用println(b.x)
,没有问题。与Nate一样,Xcode B7中没有问题,所以我尝试了这个简化的示例,它确实对我有效。。。除了粘贴几个kloc,我不知道如何显示实际的故障代码。。。我可以肯定地说,Q中提到的一行更改修复了它,因此该错误似乎与使用对象的协议类型有关。我在Denit调用中也做了一个错误输出,错误确实显示了我实际上得到了Denit调用两次,有时是因为实际上有两个类,B和C(B是C的所有者),它们具有var protocolObject:SomeProtocol声明。它们似乎都在试图去识别协议类型的对象。我还创建了一个新的、独特的对象,只是为了测试它,并确保我没有以某种方式破坏程序中其他地方的引用。错误仍然发生。此解决方法已成功,谢谢。希望苹果会修复,否则就不能声明这些引用是弱的。
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)")
}
}