Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare AnyObjects in Swift without casting them to a specific type

An attempt to compare two objects of AnyObject type using '==' operator defined in Equatable protocol result in a compile error in Swift. Did anyone find a way to compare such objects, without knowing the real type of objects that can be used for downcasting?

The background for this question is that I have a dictionary Dictionary<String, AnyObject> where values are supposed to be provided though a subscript, then at some point I need to compare the values in the dictionary to make sure that they are unique.

EDIT Here is a snippet demonstrating the issue.

@objc(FooObject)
public class FooObject: NSManagedObject {

    @NSManaged public var properties: Dictionary<String, AnyObject>

    public subscript(property: String) -> AnyObject? {
        get {
            return properties[property]
        }
        set(newValue) {

            for propertyValue in properties.values {
                if propertyValue == newValue { // This line is not compiling: Cannot invoke '==' with AnyObject
                    println("Values in are expected to be unique!")
                    // Throw an exception here ...
                }
            }

            properties[property] = newValue
        }
    }
}

Note that generic like <T:Equatable> declared in the class definition and used as a value type of the dictionary won't solve the issue as it cannot be used in conjunction with NSManagedObject subclass.

like image 959
DevGansta Avatar asked Sep 17 '14 22:09

DevGansta


People also ask

How can I compare two swifts?

We can check if two sets are equal in Swift by using the equality operator == . Two sets are equal if both contain the same elements. If they are equal, the operator returns true. Otherwise, it returns false .

What is the difference between any and AnyObject in Swift?

Any and AnyObject are two special types in Swift that are used for working with non-specific types. According to Apple's Swift documentation, Any can represent an instance of any type at all, including function types and optional types. AnyObject can represent an instance of any class type.

When to use AnyObject protocol?

You use AnyObject when you need the flexibility of an untyped object or when you use bridged Objective-C methods and properties that return an untyped result. AnyObject can be used as the concrete type for an instance of any class, class type, or class-only protocol.

How to check type in Swift?

“Use the type check operator (is) to check whether an instance is of a certain subclass type. The type check operator returns true if the instance is of that subclass type and false if it is not.” Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.


2 Answers

Use the === operator, from the Swift documentation:

Swift also provides two identity operators (=== and !==), which you use to test whether two object references both refer to the same object instance.

like image 151
SpareTime Avatar answered Oct 24 '22 11:10

SpareTime


I don't think this is possible. The problem is that Equatable is defined with a method that takes

func ==(a: T, b: T)

and there's no way, at compile-time, the compiler can find the correct function (as it doesn't know the types ahead of time).

The only way you could do this is if you had some idea of the types you were comparing. Then you could concretely call the appropriate equality function for each type:

func compare(a: AnyObject, b: AnyObject) {    
    if let va = a as? Int, vb = b as? Int            {if va != vb {return false}}
    else if let va = a as? String, vb = b as? String {if va != vb {return false}}
    else if let va = a as? Bool, vb = b as? Bool     {if va != vb {return false}}
            ...
    else {
        // not a type we expected
        return false;
    }
}

It's interesting that C#, for instance, gets around this by defining the IComparable interface as having a method:

int CompareTo(Object obj)

This allows every IComparable object to compare itself with any other object (but the function has to always do its own type-checking here, to make sure obj is of the correct type).

like image 9
MattM Avatar answered Oct 24 '22 11:10

MattM