Fried Rice
Fried Rice

Reputation: 3713

Swift type comparison against stored type

I have a class that collects Types into an array, then decides whether an object is of one of the types:

struct Item: Hashable {}

class TypeChecker {
    let typeCollection: [Any.Type] = [Item.self]
    
    func acceptObject(_ object: Any) -> Bool {
        typeCollection.contains(where: { type(of: object) == $0 })
    }
}

let checker = TypeChecker()

let object1: Item = Item()
checker.acceptObject(object1) // returns true

let object2: AnyHashable = Item()
checker.acceptObject(object2) // returns false

In the simplified snipped above, explicitly typed object1 works correctly, however, abstractly typed object2 fails. What gives? How would I fix the TypeChecker?

Upvotes: 2

Views: 62

Answers (1)

Aleksey Gotyanov
Aleksey Gotyanov

Reputation: 550

Approach 1: When acceptable types are known at compile time.

Create a marker protocol and add conformances for acceptable types:

protocol AcceptableForSomeActionType { }

extension Item: AcceptableForSomeActionType { }

class TypeChecker {
    func acceptObject(_ object: Any) -> Bool {
        object is AcceptableForSomeActionType
    }
}

Approach 2: When acceptable types are known at runtime.

Create a protocol for container types that provides real object type.

protocol ObjectContainer {
    var objectType: Any.Type { get }
}

extension AnyHashable: ObjectContainer {
    var objectType: Any.Type { type(of: base) }
}

class TypeChecker {
    private let typeIdentifiers: Set<ObjectIdentifier> = [ObjectIdentifier(Item.self)]

    func acceptObject(_ object: Any) -> Bool {
        let objectType = (object as? ObjectContainer)?.objectType ?? type(of: object)
        return typeIdentifiers.contains(ObjectIdentifier(objectType))
    }
}

Upvotes: 1

Related Questions