Comparing objects in an Array extension causing error in Swift

I’m trying to build an extension that adds some of the convenience functionality of NSArray/NSMutableArray to the Swift Array class, and I’m trying to add this function:

func indexOfObject(object:AnyObject) -> Int? {

    if self.count > 0 {
        for (idx, objectToCompare) in enumerate(self) {
            if object == objectToCompare {
                return idx
            }
        }
    }

    return nil
}

But unfortunately, this line:

  • how to send data from UIViewController to UITabBarControllers first tab in swift ios
  • Scaling a font on a multilined UIButton depending on a device size
  • Core Data: Add a column on a table
  • How we can add additional UILabels to UINavigation?
  • How to access a custom function from any file in the same Swift project?
  • How to pass data from modal view controller back when dismissed
  • if object == objectToCompare {
    

    Is giving the error:

    could not find an overload for ‘==’ that accepts the supplied arguments

    Question

    What am I doing wrong to cause this error?

    Example

    extension Array {
    
        func indexOfObject(object:AnyObject) -> Int? {
    
            if self.count > 0 {
                for (idx, objectToCompare) in enumerate(self) {
                    if object == objectToCompare {
                        return idx
                    }
                }
            }
    
            return nil
        }
    
    } 
    

    6 Solutions Collect From Internet About “Comparing objects in an Array extension causing error in Swift”

    You can always create an extension that uses NSArray’s indexOfObject, e.g:

    extension Array {
        func indexOfObject(object:AnyObject) -> Int? {
            return (self as NSArray).indexOfObject(object)
        }
    }
    

    You can specify that your array items can be compared with the <T : Equatable> constraint, then you can cast your object into T and compare them, e.g:

    extension Array {
        func indexOfObject<T : Equatable>(o:T) -> Int? {
            if self.count > 0 {
                for (idx, objectToCompare) in enumerate(self) {
                    let to = objectToCompare as T
                    if o == to {
                        return idx
                    }
                }
            }
    
            return nil
        }
    }
    

    Actually there is no need to implement indexOfObject:; there is a global function find(array, element) already.

    My guess is that you have to do something like this:

    func indexOfObject<T: Equatable>(object: T) -> Int? {
    

    and so on.

    Here’s a relevant example from Apple’s “The Swift Programming Language” in the “Generics” section:

    func findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? {
        for (index, value) in enumerate(array) {
            if value == valueToFind {
                return index
            }
        }
        return nil
    }
    

    The key idea here is that both value and valueToFind must of a type that is guaranteed to have the == operator implemented/overloaded. The <T: Equatable> is a generic that allows only objects of a type that are, well, equatable.

    In your case, we would need to ensure that the array itself is composed only of objects that are equatable. The Array is declared as a struct with a generic <T> that does not require it to be equatable, however. I don’t know whether it is possible to use extensions to change what kind of types an array can be composed of. I’ve tried some variations on the syntax and haven’t found a way.

    You can extract the compare part to another helper function, for example

    extension Array {
        func indexOfObject(object: T, equal: (T, T) -> Bool) -> Int? {
    
            if self.count > 0 {
                for (idx, objectToCompare) in enumerate(self) {
                    if equal(object, objectToCompare) {
                        return idx
                    }
                }
            }
    
            return nil
        }
    }
    
    let arr = [1, 2, 3]
    
    arr.indexOfObject(3, ==) // which returns {Some 2}
    

    You were close. Here’s a working extension:

    extension Array {
        func indexOfObject<T: Equatable>(object:T) -> Int? {
            if self.count > 0 {
                for (idx, objectToCompare) in enumerate(self) {
                    if object == objectToCompare as T {
                        return idx
                    }
                }
            }
            return nil
        }
    }
    

    Swift had no way of knowing if object or objectToCompare were equatable. By adding generic information to the method, we’re then in business.