Using enum and switch case combination in Swift [duplicate] - iphone

This question already has answers here:
Switch in Swift - Case label in a switch should have at least one executable statement
(2 answers)
Noop for Swift's Exhaustive Switch Statements
(8 answers)
Closed 7 years ago.
Here is my code:
enum GameScreen
{
case kSceneFlashScreen
case kSceneMainMenu
case kSceneGameScreen
case kSceneStoreScreen
case kSceneGameOver
}
class YSGameManager: NSObject {
func replaceGameScene(inScreen: GameScreen)
{
switch inScreen
{
case GameScreen.kSceneGameScreen: //Error for here
case GameScreen.kSceneMainMenu : //here also error
}
}
}
Eror LOG: 'case' label in a 'switch' should have at least one executable statement
How to use enum in switch case in Swift ?

There's an error because you haven't got anything after : and before the next case. To solve this you can:
1. Add some code to do something.
2. Add fallthrough if you want to move to the next case. This may have been what you were trying to do. However, in Swift, switch statements don't fallthrough by default to the next case, they break.
3. Add break to stop the switch statement.

It’s complaining that you need to actually do something after the matching case. Otherwise there’s not much point matching it, and chances are it’s a typo.
Other possibly than coverage i.e. if you don’t want a default, you want to name every possible enum, even though you don’t want to do anything for some of them. In which case, stick in a break:
switch inScreen {
case kSceneGameScreen:
break
// etc.
}
Note, there’s no implicit fall through in Swift’s switch statements. You need to give one explicitly:
switch inScreen {
case kSceneGameScreen:
// do a game-screen-specific thing
fallthrough // then
case kSceneMainMenu:
// do a thing for both
// kSceneGameScreen and kSceneMainMenu
// etc.
}
But if you just want to match two possibilities, you don’t need to use fall through, you can just combine them with ,:
switch inScreen {
case kSceneGameScreen, kSceneMainMenu:
// do a thing for both
// kSceneGameScreen and kSceneMainMenu
// etc.
}

Related

Using #unknown default in swift 5 enum : How to suppress "Default will never be executed" warning?

Let's say I have an existing code as follows:
enum SomeEnumCases {
case existing
case alreadyExisting
}
func doSomething(withEnums enumCase: SomeEnumCases) {
switch enumCase {
case .existing:
print("This case was already existing")
case .alreadyExisting:
print("This case was already existing too...")
}
}
Now, if I were to add a new case the the enum, the function above would show a compile error saying the switch case must be exhaustive, and I would be FORCED to handle the new missing case. I would add a third case in the switch statement, or add a default statement.
Now, I order to handle such unforeseen enum cases, I would like to add an #unknown default case to the existing function above. The only problem is, now it would give me a warning saying Default will never be executed.
So the question is, how do I future-proof my enum such that I can:
Exhaustively handle all current enum cases, AND
Have a default handling mechanism for the future unknown case, AND
See a warning only when newer cases are added and these cases must be handled by the default case.
That means, the following code SHOULD NOT give warnings:
enum SomeEnumCases {
case existing
case alreadyExisting
}
func doSomething(withEnums enumCase: SomeEnumCases) {
switch enumCase {
case .existing:
print("This case was already existing")
case .alreadyExisting:
print("This case was already existing too...")
#unknown default: // <-- warning: Default will never be executed: should be suppressed
print("Alright, this is something new and exciting !!")
}
}
but the following code SHOULD give a warning:
enum SomeEnumCases {
case existing
case alreadyExisting
case new
}
func doSomething(withEnums enumCase: SomeEnumCases) {
switch enumCase { // <-- warning: Switch must be exhaustive: This should stay.
case .existing:
print("This case was already existing")
case .alreadyExisting:
print("This case was already existing too...")
#unknown default:
print("Alright, this is something new and exciting !!")
}
}
Is that possible through #unknown or otherwise ?
The warning is probably somewhat misleading as the spec says (emphasis added):
A nonfrozen enumeration is a special kind of enumeration that may gain new enumeration cases in the future—even after you compile and ship an app. Switching over a nonfrozen enumeration requires extra consideration. When a library’s authors mark an enumeration as nonfrozen, they reserve the right to add new enumeration cases, and any code that interacts with that enumeration must be able to handle those future cases without being recompiled. Only the standard library, Swift overlays for Apple frameworks, and C and Objective-C code can declare nonfrozen enumerations. Enumerations you declare in Swift can’t be nonfrozen.
So it's not so much that the branch will never be executed but that the feature is completely unsupported for your SomeEnumCases user-defined Swift enum.
There seems to be no supported way of doing what you wish in Swift 5, and some indications that adding cases is seen as a breaking change as it could/would break binary compatibility, but Swift is an ever moving target...

Swift switch statement force to write block of code [duplicate]

This question already has answers here:
Noop for Swift's Exhaustive Switch Statements
(8 answers)
Closed 5 years ago.
I have question, i have enum with 3 state. On 2 of 3 that state i want to do something, but for 3rd i do not. However, when i do not put block of code below case, compiler highligh it with red and won't allow me to run app. Example:
func leftBarButtonTappedWithType(type: CustomNavBarViewModel.LeftBarButtonType) {
switch type {
case .none:
print("")
case .back:
self.popViewController(animated: true)
case .hamburger:
self.func()
}
}
You can see that for case .none i wrote print("") because in other case i won't be able to compile. How to avoid that? Kind of ugly.
Just get your function to return in that case:
case .hamburger:
return
Hope that helps.
Per the discussion and #MartinR 's comment, break is probably a better general solution to exit the switch statement.

Is there a NULL statement in Swift? [duplicate]

This question already has answers here:
Noop for Swift's Exhaustive Switch Statements
(8 answers)
Closed 8 years ago.
Compiler complain about the lack of at least one executable statement on case label in a switch :
switch someData {
case .one:
// No statements
// Error occurs here
case .two:
// Some statements here
default:
// Some statements here
}
Here is the exact message:
'case' label in a 'switch' should have at least one executable statement
So is there any statement that do nothing to satisfy compiler requirement?
I know a simple statement like print() can do the job but I wonder if there is a specific one?
In other language, Ada for example there is a nullstatement to achieve this.
Set break or return, depending on what you want to do.
switch someData {
case .one:
nil
case .two:
// Some statements here
default:
// Some statements here
}

Pass Keyword in Swift

I know that the keyword "pass" in Python will allow one to leave a line of code empty where it should have contained an executable statement. Is there a similar keyword in Swift?
I am using a switch statement and Swift requires there to be a default case. The code should reach the default statement most of the time and I want nothing to be done in this case.
You can break out of the default case. Swift just wants you to be explicit about that to avoid bugs.
Here's a simple example:
enum Food {
case Banana
case Apple
case ChocolateBar
}
func warnIfUnhealthy(food : Food) {
switch food {
case .ChocolateBar:
println("Don't eat it!")
default:
break
}
}
let candy = Food.ChocolateBar
warnIfUnhealthy(candy)
The proper way to add a catch-all without an action to a switch statement is to add
default: break
at the end.

Combine default case with other cases

Given the following enum in C# and a switch/case to return the a border color of a textbox according its state for example.
enum TextboxState {
Default,
Error
}
switch(foo) {
default:
case TextboxState.Default: return Color.Black;
case TextboxState.Error: return Color.Red;
}
So basically I define a real and not just by convention default state aka TextboxState.Default by adding the default: case. I just want to do this to prevent future breaking changes if new values are added to the enum.
According to the Swift book this is not possible:
“If it is not appropriate to provide a switch case for every possible
value, you can define a default catch-all case to cover any values
that are not addressed explicitly. This catch-all case is indicated by
the keyword default, and must always appear last.”
The paragraph is quite clear about that, so I assume my pattern above does not apply to Swift or do I miss something? Is there another way to archive something like the above code?
You can use fallthrough to do that, by moving the shared behavior in the default case, and using fallthrough in all cases for which you want the shared behavior to occur.
For example, if this is your enum (added a 3rd case to show it can handle multiple fall throughs):
enum TextboxState {
case Default
case Error
case SomethingElse
}
you can format the switch statement as follows:
switch(foo) {
case TextboxState.Error:
return UIColor.redColor()
case TextboxState.Default:
fallthrough
case TextboxState.SomethingElse:
fallthrough
default:
return UIColor.blackColor()
}
Each fallthrough moves the execution point to the next case, up to the default case.
Delete the default: line from your switch. Even if you someday add additional cases to your enum, the Swift compiler will complain if you don't add corresponding cases to every switch that uses the enum. And FYI, you don't need to specify the TextboxState. before the case values in the switch, because the compiler knows that foo is a TextboxState. The resulting code would be:
switch(foo) {
case .Default: return Color.Black;
case .Error: return Color.Red;
}
although, for consistency, I'd put the .Error case before the .Default one.