Storing and then casting to Metatypes in Swift [duplicate]
Asked Answered
P

1

7

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 {

Parmesan answered 22/4, 2016 at 18:9 Comment(0)
O
9

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.

Outflank answered 22/4, 2016 at 18:32 Comment(5)
Aw :'( Why fortunately, would you say?Parmesan
@cilk, well, i have another answer for you, man :) https://mcmap.net/q/45494/-what-is-the-difference-between-statically-typed-and-dynamically-typed-languagesOutflank
Ah yeah, fair enough. Great for safety until I want to be unsafe.. Did you approach an alternate solution?Parmesan
ah well, I'll find some way :)Parmesan
In my use case, I actually didn't need to cast to the Type itself. The Type was always a subclass, and the information I was passing would always go to the Type's super, so I cast to the super instead. What's weird is that I did need to access a class method on the type, which it did allow me to do. cell = collectionView.dequeueReusableCellWithReuseIdentifier(type.reuseIdentifierId, forIndexPath: indexPath) as? SuperType Were type is the metatype in question!Parmesan

© 2022 - 2024 — McMap. All rights reserved.