Swift:通过整数加载级别类

4
我正在制作一款有很多关卡的Swift游戏,每个关卡都在一个按顺序命名的文件中:
Level1.swift
Level2.swift
Level3.swift
...

每个文件都有一个单独的类,类名与文件名相同。

之所以所有东西都是类,是因为所有类都从基类继承了相似的功能,也因为有很多共享变量。

问题是,我不知道如何仅使用整数加载级别,而不进行这种灾难性的操作:

switch Int(level)! {
  case 1:
    newScene = Level1(size: frame.size)
  case 2:
    newScene = Level2(size: frame.size)
  case 3:
    newScene = Level3(size: frame.size)
  ...

因为我没有任何.sks文件,只有实际的类,所以我无法使用SKScene(fileNamed:)。如果我可以像使用音频文件一样使用Bundle.main.url加载场景,那就太好了,但这是不可能的。我尝试使用协议和扩展来实现默认行为,但我仍然无法想到一个好的加载方式。欢迎提供任何帮助。

2个回答

2
我认为您所谓的“灾难性”解决方案在Swift中提供了最干净、类型检查过的解决方案。如果您想要根据仅在运行时已知的名称初始化一个类,则必须进入ObjC领域:
首先,让基类从NSObject继承(如果它还没有):
class Level : NSObject {
    var levelId: Int = 0

    required init(size: NSSize) { }
    // all other common stuffs here
}

class Level1 : Level {
    required init(size: NSSize) {
        super.init(size: size)
        self.levelId = 1
        // ...
    }
}

class Level2 : Level {
    required init(size: NSSize) {
        super.init(size: size)
        self.levelId = 2
        // ...
    }
}

class Level3 : Level {
    required init(size: NSSize) {
        super.init(size: size)
        self.levelId = 3
        // ...
    }
}

以下是如何使用它的步骤:
let levelId = 2

// Module Name = Product Name from your Build Settings, unless you put
// the Level classes into sub-namespace
let className = "ModuleName.Level\(levelId)"    

let LevelClass = NSClassFromString(className) as! Level.Type

// At build time, the compiler sees this as an object of type Level,
// but it's actually a Level2 object. You can cast it to Level2 if
// you need to do something specific to that level.
let level = LevelClass.init(size: frame.size)       

1
你需要获取你的类的classString,幸运的是,你的类呈现出一种共同的模式,所以这对你来说很容易。这里有一个代码片段让你测试
import Foundation

class Level  {
    required init() {}
}

class Level1 : Level {
     required init() {
        print("Created Level 1")
    }
}
class Level2 : Level {
    required  init() {
        print("Created Level 2")
    }
}

var myLevelClassRealName = NSStringFromClass(Level.self)
print("This String is what we need : \(myLevelClassRealName)")

var level = 2
print("The Level I want to load is Level # \(level)")
myLevelClassRealName = myLevelClassRealName + "\(level)"
print("Real name for my class is   : " + myLevelClassRealName)

let myLookupClass = NSClassFromString(myLevelClassRealName) as! Level.Type
let currentLevel = myLookupClass.init()

print("Created a class of type     : \(type(of: currentLevel))")

在我的情况下,输出结果为:

我们需要的字符串是:TempCode.Level

我想要加载的关卡是第2关

我的类的真实名称是:TempCode.Level2

创建了第2关

创建了一个类型为Level2的类


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接