我正在尝试使用Comparable扩展我的协议选项以使用简单的.sort()方法.
以下简短示例仅使用Equatable来显示错误.
@objc protocol Option: Equatable {
var title: String { get }
var enabled: Bool { get }
var position: Int { get }
}
func ==(lhs: Option,rhs: Option) -> Bool {
return lhs.position == rhs.position
}
Option协议必须标记为@objc或从NSObjectProtocol继承,因为它将与UIKit一起使用.
错误:
>
@objc protocol ‘Option’ cannot refine non-@objc protocol
‘Equatable’
>
Protocol ‘Option’ can only be used as a generic constraint
because it has Self or associated type requirements
你有什么建议如何解决这个问题?
解决方法
只能在Swift世界中生活,因此您无法将其扩展到Objective-C将使用的协议.尝试这样做会导致错误#1
具有Self要求的协议(即,协议声明中的至少一个方法包含Self)不能用作函数或变量声明的参数,仅作为泛型子句的参数,例如,func doSomething< T:Option>(参数:T).
从Option协议声明中删除Equatable,并在Option上声明== as generic将解决编译错误.至于排序,你也可以重载<运算符,并通过该运算符排序(无需实现Comparable):
@objc protocol Option {
var title: String { get }
var enabled: Bool { get }
var position: Int { get }
}
func ==<T: Option>(lhs: T,rhs: T) -> Bool {
return lhs.position == rhs.position
}
func <<T: Option>(lhs: T,rhs: T) -> Bool {
return lhs.position < rhs.position
}
这允许您将符合协议的对象传递给UIKit,并在快速代码中对它们进行比较.
class A: NSObject,Option { .. }
class B: NSObject,Option { ... }
let a = A()
let b = B()
a == b // compiles,and returns true if a and b have the same position
let c: [Option] = [a,b]
c.sort(<) // returns a sorted array by the `position` field
关于上面的排序代码的一个重要注意事项:如果你没有为c指定类型,那么编译器会将其类型推断为[NSObject],并且由于<的不明确性,排序调用将无法编译.操作符.您需要将c显式声明为[Option]以利用重载运算符.