I've come across a strange issue related to Swift/Objective-C interoperability. The case is this:
I have an @objc public class GKDistance:NSObject,NSCoding,Comparable
written in Swift. In order to compare distances, I have added an operator overload for <
as follows:
public func <(a:GKDistance, b:GKDistance) -> Bool {
return a.value < b.value
}
public func ==(a:GKDistance, b:GKDistance) -> Bool {
return a.value == b.value
}
It's then used in an Objective-C method like so:
if (distance < averageDistance){
// code
}
When the Objective-C method is called I can add a print()
statement and breakpoint in the <
method to confirm when the operator overload is being used. In one case, it mysteriously skips the operator overload defined in Swift, and uses the regular Objective-C comparator between two GKDistance objects.
When run with distance.value == 2375.1842554877021
and averageDistance.value == 75.671794891357421
, distance < averageDistance
returns true
, the Swift operator overload is never hit, and Objective-C executes the code inside the conditional.
If I convert the Objective-C method in question to Swift, it behaves as expected, but I'm concerned that there are other GKDistance comparisons in various Objective-C methods throughout our app that could be failing to see the Swift operator overload.
Has anyone run into similar issues with Swift/Objective-C interoperability as it pertains to operator overloading?
Your
public func <(a:GKDistance, b:GKDistance) -> Bool { }
is – like all Swift operators – a top-level function, and top-level functions are not exported to Objective-C, see "Swift Type Compatibility" in "Interacting with Objective-C APIs".
Also note that you cannot override operators (like <
) in (Objective-)C, see e.g.
Therefore in
if (distance < averageDistance) {
// code
}
just the two pointers are compared, and the condition is true if
the object pointed to by distance
resides in a lower memory address
than the object pointer to by averageDistance
(which is obviously
not what you intended).
What you could do is to implement a compare:
method in your class,
similar to the one of NSString
or NSNumber
.
Note also that for NSObject
subclasses, you should override
isEqual:
instead of implementing ==
, compare
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With