Memory management Swift协议对象弧

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() {

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_访问。但是,如果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)")
    }

}