2016-01-14 39 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(<)