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

时间:2016-01-14 10:52:13

标签: ios swift protocols comparable

我正在尝试使用Option扩展我的协议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一起使用。

错误:

  1.   

    @objc protocol' Option'无法改进非@objc协议   ' Equatable'

  2.   

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

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

2 个答案:

答案 0 :(得分:4)

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

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

Equatable协议声明中删除Option,并在==上将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]以利用重载运算符。

答案 1 :(得分:2)

可以通过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(<)