我需要一个只能由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