I have a view controller that will show users a "question drill down", where answering one question shows the next assigned question based on the previous answer. I'm trying to figure out the best way to structure this "question drill down".
I'm assuming nested enums is the way to go. Here's an example of the setup I currently have:
enum SubmissionSteps {
case techQuestion(TechQuestionStep)
enum TechQuestionStep {
case website(WebsiteStep), app, password, other
enum WebsiteStep {
case yesStreaming(YesStreamingStep), noStreaming
enum YesStreamingStep {
case startTime(StartTimeStep)
enum StartTimeStep {
case endTime
}
}
}
}
}
func showFirstStep() {
currentStep = SubmissionSteps.techQuestion // error here 'ViewController' has no member 'techQuestion'
}
var currentStep:SubmissionSteps? {
didSet {
}
}
var currentlyShowing:[SubmissionSteps] = [] {
didSet {
}
}
func getStepTitle(step:SubmissionSteps) -> String {
switch step {
case .techQuestion(_):
return "Tech Question"
case .techQuestion(.app):
return "App" // Case is already handled by previous patterns;
case .techQuestion(.other):
return "Other" // Case is already handled by previous patterns;
case .techQuestion(.password):
return "Password" // Case is already handled by previous patterns;
case .techQuestion(.website(_)):
return "Website" // Case is already handled by previous patterns;
case .techQuestion(.website(.noStreaming)):
return "No Streaming" // Case is already handled by previous patterns;
case .techQuestion(.website(.yesStreaming(_))):
return "Yes Streaming" // Case is already handled by previous patterns;
case .techQuestion(.website(.yesStreaming(.startTime(_)))):
return "Start Time" // Case is already handled by previous patterns;
case .techQuestion(.website(.yesStreaming(.startTime(.endTime)))):
return "End Time" // Case is already handled by previous patterns;
}
}
The issue with the setup above exists in the getStepTitle()
func. I can't return the title for a parent option, only the titles for the children. The switch statement in the getStepTitle()
func that I currently have shows "Case is already handled by previous patters; consider removing it".
I also can't set the currentStep
to be a parent option in the enum, only the children.
Either using nested enums in not the proper way to handle a data setup like this, or I have a basic misunderstanding of how to access parent values within the nested enum to get the current title for any level inside the enum. Suggestions or thoughts?
Your current use of enum associated values doesn't allow you to create "parent" values. For example, currentStep = SubmissionSteps.techQuestion
doesn't work because techQuestion
requires an associated value.
I see two solutions.
case
to represent a "top" level.For solution 1 your nested enum becomes:
enum SubmissionSteps {
case techQuestion(TechQuestionStep?)
enum TechQuestionStep {
case website(WebsiteStep?), app, password, other
enum WebsiteStep {
case yesStreaming(YesStreamingStep?), noStreaming
enum YesStreamingStep {
case startTime(StartTimeStep?)
enum StartTimeStep {
case endTime
}
}
}
}
}
And you can create a "parent" techQuestion
with:
currentStep = SubmissionSteps.techQuestion(nil)
You resolve the issues with getStepTitle
by putting the most specific cases first and the most general last:
func getStepTitle(step:SubmissionSteps) -> String {
switch step {
case .techQuestion(.website(.yesStreaming(.startTime(.endTime)))):
return "End Time"
case .techQuestion(.website(.yesStreaming(.startTime(_)))):
return "Start Time"
case .techQuestion(.website(.yesStreaming(_))):
return "Yes Streaming"
case .techQuestion(.website(.noStreaming)):
return "No Streaming"
case .techQuestion(.website(_)):
return "Website"
case .techQuestion(.password):
return "Password"
case .techQuestion(.other):
return "Other"
case .techQuestion(.app):
return "App"
case .techQuestion(_):
return "Tech Question"
}
}
For solution 2 your nested enum becomes something like:
enum SubmissionSteps {
case techQuestion(TechQuestionStep)
enum TechQuestionStep {
case top
case website(WebsiteStep), app, password, other
enum WebsiteStep {
case top
case yesStreaming(YesStreamingStep), noStreaming
enum YesStreamingStep {
case top
case startTime(StartTimeStep)
enum StartTimeStep {
case endTime
}
}
}
}
}
And you can create a "parent" techQuestion
with:
currentStep = SubmissionSteps.techQuestion(.top)
The fix for getStepTitle
is the same.
As for your statement: "I'm assuming nested enums is the way to go.", that's a whole other discussion well beyond the scope here.