在 Swift 中使用 Comparable 扩展 @objc 协议
Extend @objc protocol with Comparable in Swift
我正在尝试使用 Comparable
扩展我的协议 Option
以使用简单的 .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
你对如何解决这个问题有什么建议吗?
Equatable
仅存在于 Swift 世界中,因此您不能将其扩展到 Objective-C 将使用的协议。尝试这样做会导致错误 #1
具有 Self
要求的协议(即协议声明中至少有一个方法包含 Self
)不能用作函数或变量声明的参数,只能用作通用条款,例如func doSomething<T: Option>(argument: T)
.
从 Option
协议声明中删除 Equatable
,并在 Option
上将 ==
声明为通用将解决编译错误。至于排序,您还可以重载 <
运算符,并通过该运算符进行排序(无需实现 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
,并在您的 swift 代码中比较它们。
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]
,并且 sort
调用由于 <
运算符的歧义,将无法编译。您需要将 c
显式声明为 [Option]
以利用重载运算符。
此问题可以通过 swift 2.0
中引入的新的面向协议的编程功能来解决
@objc protocol 'Option' cannot refine non-@objc protocol 'Equatable'
如错误所述,Equatable
协议是一个 swift 协议,您不能将其用于 Obj C 上下文
Protocol 'Option' can only be used as a generic constraint because it
has Self or associated type requirements
您可以通过以下方式实现:
@objc protocol Option {
var title: String { get }
var enabled: Bool { get }
var position: Int { get }
}
extension Equatable where Self : Option
{
}
extension Comparable where Self : Option
{
}
func ==(lhs: Option, rhs: Option) -> Bool
{
return lhs.position == rhs.position
}
func <(lhs: Option, rhs: Option) -> Bool
{
return lhs.position < rhs.position
}
func >(lhs: Option, rhs: Option) -> Bool
{
return lhs.position > rhs.position
}
你的 class 和实现看起来像:
class MyClass: Option
{
@objc var title: String = ""
@objc var enabled: Bool = true
@objc var position: Int = 0
init()
{
}
convenience init(title : String, enabled : Bool, position: Int)
{
self.init()
self.title = title
self.enabled = enabled
self.position = position
}
}
let firstObj = MyClass()
let secondObj = MyClass()
let optionArray : [Option] = [firstObj, secondObj]
// Sort array of options
optionArray.sort(<)
我正在尝试使用 Comparable
扩展我的协议 Option
以使用简单的 .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
你对如何解决这个问题有什么建议吗?
Equatable
仅存在于 Swift 世界中,因此您不能将其扩展到 Objective-C 将使用的协议。尝试这样做会导致错误 #1
具有 Self
要求的协议(即协议声明中至少有一个方法包含 Self
)不能用作函数或变量声明的参数,只能用作通用条款,例如func doSomething<T: Option>(argument: T)
.
从 Option
协议声明中删除 Equatable
,并在 Option
上将 ==
声明为通用将解决编译错误。至于排序,您还可以重载 <
运算符,并通过该运算符进行排序(无需实现 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
,并在您的 swift 代码中比较它们。
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]
,并且 sort
调用由于 <
运算符的歧义,将无法编译。您需要将 c
显式声明为 [Option]
以利用重载运算符。
此问题可以通过 swift 2.0
中引入的新的面向协议的编程功能来解决@objc protocol 'Option' cannot refine non-@objc protocol 'Equatable'
如错误所述,Equatable
协议是一个 swift 协议,您不能将其用于 Obj C 上下文
Protocol 'Option' can only be used as a generic constraint because it has Self or associated type requirements
您可以通过以下方式实现:
@objc protocol Option {
var title: String { get }
var enabled: Bool { get }
var position: Int { get }
}
extension Equatable where Self : Option
{
}
extension Comparable where Self : Option
{
}
func ==(lhs: Option, rhs: Option) -> Bool
{
return lhs.position == rhs.position
}
func <(lhs: Option, rhs: Option) -> Bool
{
return lhs.position < rhs.position
}
func >(lhs: Option, rhs: Option) -> Bool
{
return lhs.position > rhs.position
}
你的 class 和实现看起来像:
class MyClass: Option
{
@objc var title: String = ""
@objc var enabled: Bool = true
@objc var position: Int = 0
init()
{
}
convenience init(title : String, enabled : Bool, position: Int)
{
self.init()
self.title = title
self.enabled = enabled
self.position = position
}
}
let firstObj = MyClass()
let secondObj = MyClass()
let optionArray : [Option] = [firstObj, secondObj]
// Sort array of options
optionArray.sort(<)