2016-01-14 40 views
5

我试图扩展我的协议OptionComparable以使用简单的.sort()方法。在Swift中使用Comparable扩展@objc协议

下面的简短例子只能用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协议 '选项' 不能缩小非@ objc协议 'Equatable'

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

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

+0

也许ü需要使用'dynamic' decleration了变量与'objc使用' – Tj3n

+1

我在代码 – Cristik

+0

@Cristik上看不到'SelectOption'谢谢你的纠正。 – dtd

回答

3

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

+0

感谢您的回答。这是战斗的一半:)如果我想在元素集合(Element:Option)上使用.sort(),我需要将协议标记为Comparable。我已经尝试过@nonobjc声明扩展,但我不工作.. – dtd

+0

@dtd检查更新的答案,它也解决排序 – Cristik

+0

@Critic如果从Comparable'协议不可能继承,你的解决方案如果非常好,并且我会用它。我不知道我只能使用竞争运算符'c.sort(<)'。我还为数组添加了一个简单的扩展:'扩展数组,其中元素:选项{func sort() - > [Element] {return self.sort(<)}}' – dtd

2

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

@objc协议“选项”不能缩小非@ objc协议“Equatable”

作为错误状态,则Equatable协议是迅速协议,你不能向的OBJÇ上下文

协议“选项”只能或者用作通用约束,因为它具有 自相关联的类型要求

您可以通过以下方式实现这一目标:

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