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.
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 .
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.
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.
“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.
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.
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).
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