ANSWERED! I posted an answer with code that I modified from Arbitur. Thanks to Phillip as well for the key advice that lead me to redirect my searches.
TLDR:
is there a way to run a function from a string? Like RunFunction("myfunction_" + number + "()"), or, is a way to hardcode like myfunction_\&number() ?
I'm Justin and this is my first post. I've worked hard the past 2 months to not ask a question, but I'm finally breaking bad. I'll try to be brief but I'm terribly wordy (and this long intro doesn't help). Appreciation in advance for your patience.
Basically, I'm making an engine that transforms simple words and phrases into Swift code; the goal of this is to have something to quickly make Text games, educational apps, and anything involving a non-linear set of questions / answers that change based on how you respond.
Now, I'm working on what I thought would be an easy part: storing the actual text for the Labels and Buttons (I'm working in Xcode / iOS atm). I decided to model it like film-makers / novelists do: a movie is composed of Scenes which are composed of Clips. You can also think of this as Chapters / Paragraphs
So (not actual code):
App = (Scene 1 -> Scene 2 -> Scene 3, etc)
Scene 1 = (Clip 1 -> Clip 2 -> Clip 3, etc)
Scene 2 = Clip 2 -> Clip 5 -> Clip 1, based on responses
....And so on.
The way I think (and program), I tend to avoid Classes as much as possible, outside of being strictly data or strictly function structures.
So, my first solution was to create a struct (or class) with nested functions:
struct SceneList {
//fScene calls, and passes the clip# from the button click
func fPlayClip(clipNUM: Int)
{
//Do logic stuff, then play the correct clip
}
//Called from button clicks on main screen; passes in clip#
func fScene1(play_clip clipNumber: Int){
//sub functions(S1)
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}
fPlayClip(clipNumber)
}
func fScene2(play_clip clipNumber: Int){
//sub functions(S2)
func fClip1(){ print("Yo, scene 2, clip 1")}
func fClip2(){ print ("Yo, scene 2, clip 2")}
fPlayClip(clipNumber)
}
}
Unfortunately, this design failed because there is no way for me to call sub-functions from fPlayClip(), so I took another approach:
//////////////////////////
/////SceneList.swift//////
//////////////////////////
struct Scene1{
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}}
struct Scene2{
func fClip1(){ print("Yo, scene 2, clip 1")}
func fClip2(){ print ("Yo, scene 2, clip 2")}}
//////////////////////////
////////Main.swift////////
//////////////////////////
// Implemention of the structs / clips.
// (playScene is called in button click method.)
func playScene(/*button prams go here*/){
// Switch(){ case desired: // Solve for X,
var oScenePlayer = SceneX() // where X is the desired scene
// Switch(){ case desired: // Solve for Z,
oScenePlayer.fClipZ() // where Z is the desired clip
}
Again, this failed because I couldn't use just one object, [oScenePlayer], because each struct was a different type.
I then went around for a while trying to figure out a way to destroy the object, then recreate it, but I couldn't do that. Then, I looked around for a way to reassign one object to another class type, but couldn't. Then, I peered into the extensions, protocols, generic types, etc, trying to figure out a way to extend / inherent to get this to work, but failed.
So now, my final two /working/ solutions, are to just create a new object on scene changes, and wait for ARC or whatever to destroy the old one; or, for me to go back to the first example, and simply embed [fPlayScene] into every function:
//SOLUTION 1:
struct SceneList {
func fScene1(play_clip clipNumber: Int){
//sub functions(S1)
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}
//Do logic stuff below, solving for Y
case desired:
fClipY()
}
}
//SOLUTION 2:
//////////////////////////
/////SceneList.swift//////
//////////////////////////
struct Scene1{
func fClip1(){ print("I'm scene 1, clip 1")}
func fClip2(){ print ("I'm scene 1, clip 2")}}
}
//And so on...
//////////////////////////
////////Main.swift////////
//////////////////////////
//////////////////////////
// Inside the globalish area:
let oScene1: Scene1,
oScene2: Scene2
//And so on...
var global_next_scene = 1
var global_next_clip = 1
/////////////////////////////////
// Inside the button call method:
func playScene(next_scene: Int, next_clip: Int){
switch(next_scene){ //Find the scene
case 1:
oScene1 = Scene1()
switch(next_clip){ //Play the clip
case 1:
oScene1.fClip1()
}
}
Basically, I feel that I'm using WAY too many switch statements, and in way too many places, (there could be hundreds of scenes and thousands of clips), when something as simple as a RunFunction("fClip" + next_clip + "()")
would work, but I don't know of any 'execute a swift command from a string' functions :[, or something where I could hardcode like fClip\&next_clip\()
which I think was possible in c++ 15 years ago when I last programmed anything
I came up with a few other crazy ideas to implement this, I even thought about OOP (shudder) embedded classes and having member variables hold instances of the subclasses, but with my current knowledge / resources I can't find a simpler way to do this than the last 2 snippets.
All of the structs, member functions, switch statements, etc, are going to be auto-generated via my engine--so it's not that I'm looking for a faster way to do this, it just seems like an inefficient / taxing way to do it.
Any guidance would be appreciated. Thanks much in advance, and I'm surprised it's taken me this long to need to ask a question here ^-^()
Peace and blessings