Swift协议对象的ARC

时间:2014-09-08 02:55:44

标签: 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() {
        self.x = SomeClass()
        var objA = ClassA()
        objA.protocolObject = self.x
    }
}

在此示例中,当objA被取消初始化时,它会尝试取消初始化objA.protocolObject,即使仍有一个活动的引用为objB.x.这会导致运行时错误EXC_BAD_ACCESS。但是,如果ClassA定义如下:

class ClassA {
    var protocolObject: SomeClass
}

代码运行时没有错误,协议对象未被取消初始化。有什么想法吗?

1 个答案:

答案 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。