swiftgenericscastingprotocolsmetatype

Storing and then casting to Metatypes in Swift


Effectively, I want to have a protocol that will return a Metatype (e.g.: Type.Type), which I can pass to a Class, and then when I need to, cast an object to that MetaType. The reason I'm to cast it is that it will be used in a tableView dequeue function, and I want to cast to the Type I've assigned.

Consider this condensed version (full version below).

let anyObject: AnyObject = anything()

let aType = type.type() // aType here is A.Type

if let newType = anyObject as? aType {

    print(newType)
}

// error: 'aType' is not a type

I'm confused why this is not a type, since we can go aType.init() to initialise it?

The full sample code is below (and is OK to run in a Playground).

import UIKit

protocol P {

    func type() -> A.Type
}

class A {

}

class B: A {

}

class C: A {

}

struct BData: P {

    func type() -> A.Type {

        return B.self
    }
}

struct Foo {

    let type: P

    init(p: P) {

        self.type = p
    }

    func create() {

        let anyObject: AnyObject = anything()

        let typeType = type.type()

        if let newType = anyObject as? typeType {

            print(newType)
        }
    }

    func anything() -> AnyObject {

        return B()
    }
}

let data = BData()

let foo = Foo(p: data)

Playground execution failed: MyPlayground.playground:43:44: error: 'typeType' is not a type if let newType = anyObject as? typeType {


Solution

  • Ahmm. Very nice question. I had same 3-hours-pain few days ago. Finally, i found this answer, that main idea is:

    Swift's static typing means the type of a variable must be known at compile time.

    So, the way you coding unfortunately (or fortunately :) ) not allowed.