使用Swift中的Comparable扩展@objc协议

dtd*_*dtd 6 protocols comparable ios swift

我想延长我的协议OptionComparable使用简单的.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
}
Run Code Online (Sandbox Code Playgroud)

Option协议必须被标记为@objc或从继承NSObjectProtocol因为它会与被使用UIKit.

错误:

  1. @objc协议'选项'无法改进非@objc协议'Equatable'

  2. 协议'选项'只能用作通用约束,因为它具有自我或相关类型要求

你有什么建议如何解决这个问题?

Cri*_*tik 6

Equatable仅存在于 Swift 世界中,因此您无法将其扩展到 Objective-C 将使用的协议。尝试这样做会导致错误 #1

Self要求的协议(即包含协议声明中的至少一个方法Self)不能用作函数的参数或变量声明,只能用作泛型子句的参数,例如func doSomething<T: Option>(argument: T)

EquatableOption协议声明中删除,并声明==为泛型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
}
Run Code Online (Sandbox Code Playgroud)

这允许您将符合协议的对象传递给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
Run Code Online (Sandbox Code Playgroud)

关于上述排序代码的一个重要说明:如果您没有为 指定类型c,那么编译器会将其类型推断为[NSObject],并且sort由于<运算符的歧义,调用将无法编译。您需要显式声明cas[Option]以利用重载运算符。