Variable declaration in switch-case

Welcome back to Objective C-land! Last week, I doubted my own sanity more than once. One day, for example, I refactored some code to use an enum and I nearly dispaired on a simple switch-case, until I reminded myself that I've stumbled over this issue quite a while ago. But back then, I didn't write it down. Time to change this!

tl;dr: You need to open a new scope, just use curly brackets.

Happy New Year everyone! Let's start with an enum:

typedef NS_ENUM(NSInteger, Weekday) {
    WeekdayMonday,
    WeekdayTuesday,
    WeekdayWednesday,
    WeekdayThursday,
    WeekdayFriday,
    WeekdaySaturday,
    WeekdaySunday
};

Let's say, that I want to know, if I can have a beer on the evening of that day. So, let's write a method for that:

- (BOOL)iCanHazBeerOnWeekday:(Weekday)weekday {
    
    BOOL iCanHazBeer = NO;
    
    switch (weekday) {
        case WeekdayFriday:
        case WeekdaySaturday:
            NSString *cheers;
            cheers = @"Cheers! 🍻" // could be in one line
            NSLog(cheers);
            iCanHazBeer = YES;
            break;
        default:
            iCanHazBeer = NO;
            break;
    }
    
    return iCanHazBeer;
}

Everthing looks fine. But the code won't compile and Xcode complains on NSString *cheers:

Expected expression

Past-me was too self-confident: Well, this is way too easy, I don't need to stack-overflow this thing. It must be some obvious, I can solve it on my own! A variable declaration is a expression, isn't it? WHAT'S WRONG WITH U xCODE?

After some time, it came to my mind, that I saw this exact same issue a while ago: Last time, I had to use curly brackets to make it work, similar to this one:

- (BOOL)iCanHazBeerOnWeekday:(Weekday)weekday {
    
    BOOL iCanHazBeer = NO;
    
    switch (weekday) {
        case WeekdayFriday:
        case WeekdaySaturday:
        {
            NSString *cheers;
            cheers = @"Cheers! 🍻"
            NSLog(cheers);
            iCanHazBeer = YES;
        }
            break;
        default:
            iCanHazBeer = NO;
            break;
    }
    
    return iCanHazBeer;
}

This looks weird, but due to syntactic constraints, a label can't be followed by a declaration. A better explanation is given on Stack Overflow: case uses labels and in C, after a label, there has to be an expression — god knows why. And as an declaration isn't an expression, the compiler complains. This time, you can't blame ObjC, but C.

The workaround is to open a new scope and this way I can declare my variable right after a label. Well, okay, after the curly bracket after the label. But in the end, the workaround does its job — and it works.

Here you can find a a full reference for C, the relevant chapters are 6.7. Declarations and 6.8 Statements and blocks. Thank you again, Stack Overflow!

And thanks to you for reading this.