Instantiating classes stored in metatype Dictionar

2019-07-31 05:12发布

I've followed the solution at Make a Swift dictionary where the key is "Type"? to create dictionaries that can use a class type as keys. What I want to do is: I have one dictionary that should store class types with their class type (aka metatype) as keys, too:

class MyScenario {
    static var metatype:Metatype<MyScenario> {
        return Metatype(self)
    }
}


var scenarioClasses:[Metatype<MyScenario>: MyScenario.Type] = [:]

Then I have methods to register and execute scenarios:

public func registerScenario(scenarioID:MyScenario.Type) {
    if (scenarioClasses[scenarioID.metatype] == nil) {
        scenarioClasses[scenarioID.metatype] = scenarioID
    }
}

public func executeScenario(scenarioID:MyScenario.Type) {
    if let scenarioClass = scenarioClasses[scenarioID.metatype] {
        let scenario = scenarioClass()
    }
}

... Problem is in the last line:

Constructing an object of class type 'MyScenario' with a metatype value must use a 'required' initializer.

It looks like the compiler is confused at that point since I cannot use 'required' at that assignment. Does anyone have an idea how I would have to instantiate the scenarioClass in executeScenario()?

1条回答
三岁会撩人
2楼-- · 2019-07-31 05:49

This must do the job.

import Foundation

struct Metatype<T> : Hashable
{
    static func ==(lhs: Metatype, rhs: Metatype) -> Bool
    {
        return lhs.base == rhs.base
    }

    let base: T.Type

    init(_ base: T.Type)
    {
        self.base = base
    }

    var hashValue: Int
    {
        return ObjectIdentifier(base).hashValue
    }
}

public class MyScenario
{
    var p: String

    public required init()
    {
        self.p = "any"
    }

    static var metatype:Metatype<MyScenario>
    {
        return Metatype(self)
    }
}

var scenarioClasses:[Metatype<MyScenario>: MyScenario.Type] = [:]

public func registerScenario(scenarioID:MyScenario.Type)
{
    if (scenarioClasses[scenarioID.metatype] == nil)
    {
        scenarioClasses[scenarioID.metatype] = scenarioID
    }
}

public func executeScenario(scenarioID:MyScenario.Type)
{
    if let scenarioClass = scenarioClasses[scenarioID.metatype]
    {
        let scenario = scenarioClass.init()
        print("\(scenario.p)")
    }
}

// Register a new scenario
registerScenario(scenarioID: MyScenario.self)

// Execute
executeScenario(scenarioID: MyScenario.self)

// Should print "any"
查看更多
登录 后发表回答