Swift 4.2,如何为特定的类或子类定义协议

时间:2018-11-04 11:37:02

标签: swift protocols

我需要一个只能由UIView实现的协议。所以我的代码是这样的:

// Code 1
protocol FooBar where Self: UIView {
    var name: String? { get set }
}
// The default implementation.
extension FooBar {
    var name: String? {
        get {
            return objc_getAssociatedObject(self, &AssociationKey.name) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociationKey.name, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
}
private struct AssociationKey {
    static var name = 0
}

但是当我使用它时,我发现必须使用var声明该变量。

// Code 2
class TestView: UIView, FooBar {
}

let testView = TestView()
testView.name = "TestView" // Xcode Error: Cannot assign to property: 'testView' is a 'let' constant

因此,我修改了协议的定义,将AnyObject添加到协议中:

// Code 3
protocol FooBar: AnyObject where Self: UIView {
    var name: String? { get set }
}

它可以工作,但是会收到Xcode警告“冗余约束'Self':'AnyObject'“,这意味着“:AnyObject”是不必要的。

我很困惑,如果没有“ AnyObject”,该协议将无法正常工作,但是添加“ AnyObject”后,Xcode会告诉我“冗余”!

是Swift语法错误还是Xcode编译器错误?

以下代码是我的解决方案,但并不完美!因此,我希望有人告诉我一种更好的方法。谢谢!

// Code 4
protocol _FooBar: AnyObject { // define a base protocol at first
}
protocol FooBar: _FooBar where Self: UIView {
    var name: String? { get set }
}
// The default implementation.
extension FooBar {
    var name: String? {
        get {
            return objc_getAssociatedObject(self, &AssociationKey.name) as? String
        }
        set {
            objc_setAssociatedObject(self, &AssociationKey.name, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }
}
private struct AssociationKey {
    static var name = 0
}


class TestView: UIView, FooBar {

}
let testView: FooBar = TestView()
testView.name = "Test"

配置:Xcode 10.0,Swift 4.2

0 个答案:

没有答案