解包协议类型的可选弱属性时Swift EXC_BAD_ACCESS

时间:2015-05-17 21:27:18

标签: ios objective-c swift exc-bad-access

我的Xcode游乐场中有这个代码,最后一行出现EXC_BAD_ACCESS错误:

protocol SomeProtocol: class {
    func test()
}

class SomeClass: SomeProtocol {
    func test(){}
}

struct Weak<T: AnyObject> {
    weak var value: T?

    init(_ value: T) {
        self.value = value
    }
}

var value: SomeProtocol = SomeClass()
var w = Weak(value)

w.value?.test()  // EXC_BAD_ACCESS

如果我将@objc添加到协议定义而不是代码执行而没有任何错误:

import Foundation

@objc protocol SomeProtocol: class {
    func test()
}

class SomeClass: SomeProtocol {
    @objc func test(){}
}

struct Weak<T: AnyObject> {
    weak var value: T?

    init(_ value: T) {
        self.value = value
    }
}

var value: SomeProtocol = SomeClass()
var w = Weak(value)

w.value?.test()

我怀疑这些Apple文档系列与我的案例有关:

  

即使您没有与Objective-C互操作,也需要标记   你希望能够使用@objc属性的协议   检查协议一致性。

但是我不明白为什么没有@objc它不起作用。有人可以解释一下吗?

1 个答案:

答案 0 :(得分:1)

Swift目前不能很好地处理使用泛型的非类类型。

EXC_BAD_ACCESS的实际位置是Weak(value)的结果分配给var w的时间。您可以通过在println周围添加var w = Weak(value)语句来查看此内容。

要解决Swift的这些问题,您需要使用非类类型的Box值将它们与泛型一起使用。

希望在接下来的几个版本的Swift中Apple将解决这些问题,我们不再需要设置值。

final class Box<T> {
    private var value: T

    init(_ value: T) {
        self.value = value
    }

    var unbox: T {
        return value
    }
}

protocol SomeProtocol : AnyObject {
    func test()
}

class SomeClass: SomeProtocol {
    func test(){
        println("Test")
    }
}

struct Weak<T: AnyObject> {
    weak var value: T?

    init(_ value: T) {
        println("Weak Init Start")
        self.value = value
        println("Weak Init Stop")
    }
}

var value: SomeProtocol = SomeClass()

//Method in Question

println("Before Weak Init")
// var w = Weak(value) // EXC_BAD_ACCESS
println("After Weak Init")

//w.value?.test()


// Method with Box

var box = Box(value)
var w = Weak(box)

w.value?.unbox.test() // prints "Test"

w = Weak(Box(value))
w.value?.unbox.test() // nil, since nothing retains the Box(value) result