Extend @objc protocol with comparison in Swift

I am trying to extend the Option protocol to Comparable to use the simple .sort() method.

Below is a short example with Equatable only for displaying errors.

 @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 } 

The Option protocol must be marked as @objc or inherited from NSObjectProtocol because it will be used with UIKit .

Errors:

  • @Objc protocol 'Option' cannot specify non-@objc 'Equatable' protocol

  • The Variant protocol can only be used as a general restriction because it has its own or related requirements like

Do you have any suggestion to solve this problem?

+6
source share
2 answers

Equatable lives only in the Swift world, so you cannot extend it to the protocol that Objective-C will use. Attempting to do this results in error # 1

Protocols requiring Self (i.e., at least one method from a protocol declaration contains Self ) cannot be used as arguments for functions or for variable declarations only as arguments in a general sentence, for example. func doSomething<T: Option>(argument: T) .

Removing Equatable from the Option protocol declaration, and declaring == as common in Option will eliminate compilation errors. As for sorting, you can also overload the < operator and sort it through this operator (without having to execute 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 } 

This allows you to transfer objects that comply with the protocol to UIKit , as well as compare them in your fast code.

 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 

One important note about the sort code described above: if you do not specify a type for c , then the compiler will display its type as [NSObject] , and the sort call will not compile due to the ambiguity of < . You need to explicitly declare c as [Option] in order to use the overloaded operator.

+4
source

The problem can be fixed with new programming-oriented protocol features introduced in swift 2.0

The @objc "Option" protocol cannot specify the non @objc "Equatable" protocol

As the error says, the Equatable protocol is a fast protocol that cannot be used for Obj C context

The Option protocol can only be used as a general restriction, since it has its own or related requirements such as

You can achieve this as follows:

 @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 } 

And your class and implementation looks like this:

 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(<) 
+2
source

All Articles