引用类型对AnyObject类型的通用约束的协议

时间:2018-08-06 11:38:37

标签: swift class generics protocols anyobject

我有一个通用结构声明如下:

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

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

和协议:

protocol SomeProtocol: class {

}

但是我无法声明WeakReference<SomeProtocol>类型的变量,编译器抱怨

  

“ WeakReference”要求SomeProtocol为类类型

有趣的是,在Swift中,class是AnyObject的类型别名。

我实际上想保存一个WeakReference<SomeProtocol>数组,因为该数组包含强引用。

Class-only generic constraints in Swift是一个类似的问题,但并不能真正解决这个问题。

我们如何将SomeProtocol传递给WeakReference

编辑: 以下情况可以很好地编译,但是我们失去了保持弱引用的能力:

struct Reference<T> {
    var value: T?

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

var array: [Reference<SomeProtocol>] = []

3 个答案:

答案 0 :(得分:1)

您如何看待这种方法?

class WeakReference<T> {
    weak var value: AnyObject?

    init(value: T?) {
        self.value = value as? AnyObject
    }
}

protocol SomeProtocol: class {

}

class A: SomeProtocol { }

let araayOfSomeProtocolObjects: [SomeProtocol] = (0...5).map {_ in A() }
let arrayOfWeakReferences: [WeakReference<SomeProtocol>] = araayOfSomeProtocolObjects.map { WeakReference(value: $0) }

for item in arrayOfWeakReferences {
    print(item.value is A) // true
}

enter image description here

答案 1 :(得分:0)

那很简单。您正在传递SomeProtocol的{​​{1}}。您需要传递特定的类类型。

示例:

protocol

或者您可以通过使用class SomeImplementation: SomeProtocol { } var weakSome: WeakReference<SomeImplementation> = ... 批注标记协议来绕过它,但是我不喜欢这种方法。

@objc

尝试检查this answer,它可能会为您提供有关此问题的更多背景信息。

答案 2 :(得分:0)

我认为这应该可以解决您的问题。

struct WeakReference<T> {
    private weak var privateRef: AnyObject?
    var ref: T? {
        get { return privateRef as? T }
        set { privateRef = newValue as AnyObject }
    }

    init(_ ref: T? = nil) {
        self.ref = ref
    }
}

// usage
protocol MyProto: class { }
extension UIViewController: MyProto { }

let vc = UIViewController()
var weakRef = WeakReference<MyProto>(vc)
print(weakRef.ref)

您显然可以将WeakReference与非类协议或非桥接值类型一起使用。 如果尝试这样做,您将始终得到nil

P.S。 :请在实际的Xcode项目上尝试此代码,因为在Playground中无法按预期工作。