Swift: carga la class de nivel por integer

Estoy haciendo un juego Swift con muchos niveles. Cada nivel está en un file con nombres secuenciales:

Level1.swift Level2.swift Level3.swift ... 

Y cada file tiene una sola class, con el nombre de la class siendo el mismo que el nombre del file.

La razón por la que todo es una class es porque todas las classs comparten funciones similares de una class base, y también debido a muchas variables compartidas.

El problema es que no tengo idea de cómo cargar el nivel simplemente usando un integer sin hacer este tipo de desastre:

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

No puedo usar SKScene(fileNamed:) porque no tengo ningún file .sks, solo las classs reales. Sería genial si pudiera simplemente cargar una escena como puedo con files de audio, usando Bundle.main.url, pero esto no es posible. Intenté usar un protocolo con extensiones para los comportamientos pnetworkingeterminados, pero todavía no puedo pensar en una forma de cargarlo bien. Cualquier ayuda sería apreciada.

Deberás get classString para tus Clases, por suerte tus classs presentan un patrón común, por lo que esto será fácil para ti. Aquí hay un fragment con este código para que pruebes

 import Foundation class Level { requinetworking init() {} } class Level1 : Level { requinetworking init() { print("Created Level 1") } } class Level2 : Level { requinetworking 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))") 

El resultado para esto en mi caso es:

Esta cadena es lo que necesitamos: TempCode.Level

El nivel que quiero cargar es el nivel n. ° 2

El nombre real para mi class es: TempCode.Level2

Nivel 2 creado

Creado una class de tipo: Level2

Creo que su solución "desastrosa" ofrece la solución más limpia y comprobada en Swift. Si desea inicializar una class basada en un nombre conocido solo en time de ejecución, debe aventurarse en el territorio ObjC:

Primero, haga que la class base henetworkinge de NSObject (si todavía no lo hace):

 class Level : NSObject { var levelId: Int = 0 requinetworking init(size: NSSize) { } // all other common stuffs here } class Level1 : Level { requinetworking init(size: NSSize) { super.init(size: size) self.levelId = 1 // ... } } class Level2 : Level { requinetworking init(size: NSSize) { super.init(size: size) self.levelId = 2 // ... } } class Level3 : Level { requinetworking init(size: NSSize) { super.init(size: size) self.levelId = 3 // ... } } 

A continuación, le indicamos cómo utilizarlo:

 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)