2017-06-13 53 views
4

我正在制作一个很多级别的Swift游戏。每个级别与顺序名的文件: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文件,只有实际的类。如果我可以通过使用Bundle.main.url简单地加载一个场景,那就太棒了,但这是不可能的。我尝试使用默认行为的扩展协议,但我仍然想不出一种很好的加载方式。任何帮助,将不胜感激。

回答

1

您将需要获得classString你的职业,你的幸运班提出一个共同的模式,所以这将是您轻松。 Here's an snippet with this code for you to test

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

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)