首页 文章

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

提问于
浏览
6

我试图扩展我的协议 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
}

Option 协议必须标记为 @objc 或从 NSObjectProtocol 继承,因为它将与 UIKit 一起使用 .

错误:

  • @objc协议'选项'无法优化非@objc协议'Equatable'

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

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

2 回答

  • 2

    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 ,并在快速代码中对它们进行比较 .

    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] 以利用重载运算符 .

  • 4

    这个问题可以通过swift 2.0中引入的新的面向协议的编程特性来解决

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

    正如错误所述, Equatable 协议是一个swift协议,你不能对Obj C上下文

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

    您可以通过以下方式实现此目的:

    @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 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(<)
    

相关问题