Search code examples
swiftswift-protocolsequatable

AnyObject try cast to Equatable


I have an Equatable class

class Item: Equatable {
    var value: AnyObject?
    var title: String
    init(title: String, value: AnyObject?) {
        self.title = title
        self.value = value
    }
    //Equatable
    public static func ==(lhs: Item, rhs: Item) -> Bool {
        return ((lhs.title == rhs.title) && (lhs.value === rhs.value))
    }  
}

But I want cast try var value to Equatable, So that get soft equatable result

if let lValue = lhs.value as? Equatable,   // Error
   let rValue = rhs.value as? Equatable {  // Error
    valueEq = (lValue == rValue)
} else {
    valueEq = (lhs.value === rhs.value)
}

This code catch compilation error about Generic Equatable

How is I can do correct Equatable for this class?

UPD

I want use my Item in UITableViewCell in my storyboard. I Cant create generic UITableViewCell. And if I try do Item as Generic<T: Equatable> class, I will be forced to specify the types in my Cells,

var items: [Item<OnlyThisHashableClass>]

but I want use Item in Cells for any objects


Solution

  • Easy way - class stay NonGeneric, Generic only init, and in GenericInit create isEquals method

    class FieldItem: CustomStringConvertible, Equatable {
        let value: Any?
        let title: String
        private let equals: (Any?) -> Bool
        init<Value: Equatable>(title: String, value: Value?) {
            func isEquals(_ other: Any?) -> Bool {
                if let l = value, let r = other {
                    if let r = r as? Value {
                        return l == r
                    } else {
                        return false
                    }
                } else {
                    return true
                }
            }
            self.title = title
            self.value = value
            self.equals = isEquals
        }
        //CustomStringConvertible
        var description: String { get { return title } }
        //Equatable
        public static func ==(lhs: FieldItem, rhs: FieldItem) -> Bool {
            return ((lhs.title == rhs.title) && lhs.equals(rhs.value))
        }
    
    }