It seems that I've facing inconsistent behavior with Swift's indexOf function.
There are two indexOf functions in Swift:
1. The first one takes Equatable as an argument: array.indexOf(obj)
2. The second takes matching closure as an argument: array.indexOf{$0 == obj}
I have an NSObject subclass for which == operator is defined, i.e. it conforms to Equatable, therefore, I assume both function to work exactly the same (with closure in example).
However, the 1st method behaves inconsistently, in particular it returns nil when being invoked with object, instance of which is not present in array.
To illustrate issue, I provide example code with comments:
class EqObj: NSObject {
let value: Int
init(value: Int) {
self.value = value
}
}
func ==(lhs: EqObj, rhs: EqObj) -> Bool{
return lhs.value == rhs.value
}
var array = [Obj(value: 1), Obj(value: 3), Obj(value: 5)]
var object = Obj(value: 5)
// returns nil, should return 2 - incorrect
array.indexOf(object) // Instance is not present
// returns 2, correct
array.indexOf(array.last!) // Instance is present
// returns 2, correct
array.indexOf{$0 == object} // Instance is not present, predicate
// returns non-empty array, correct
array.filter{$0 == object} // Instance is not present, predicate
The issue is reproducible only with NSObject subclasses. When I change Obj: NSObject to Obj: Equatable method indexOf() works exactly as expected, i.e. returns 2.
The question is whether this can be considered a bug?
My assumption is that array.indexOf(object) invokes isEqual method of NSObject and not my overloaded == operator.
My solution:
I use array.indexOf{$0 == object}
