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}