Dominik Wagner recently wrote this post showing how he uses blocks of code (not to be mistaken for usual meaning of blocks in Objective-C) to get a value that he assigns to a variable. Although it has nothing to do with something I discovered some months ago related with blocks and switch statements, it gives me a good opportunity to document both things here.

What Dominik Wagner suggests is to stop using these constructions:

// self.myView
CGRectframe = self.myView.frame;
frame.size.width += 100.0;
frame.origin.x += 50.0;
frame.origin.y += 25.0;
self.myView.frame = frame;

// self.myButton
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100.0,300.0,50.0,50.0)];
button.backgroundColor = [UIColor orangeColor];
[button addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
self.myButton = button;

And use these instead:

// self.myView
self.myView.frame = ({
    CGRect frame = self.myView.frame;
    frame.size.width += 100.0;
    frame.origin.x += 50.0;
    frame.origin.y += 25.0;
    frame;
});

// self.myButton
self.myButton = ({
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(100.0, 300.0, 50.0, 50.0)];
    button.backgroundColor = [UIColor orangeColor];
    [button addTarget:self action:@selector(myAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    button;
});

The major benefits from this approach seem to be:

  • The assignment happens at the first line and not at the end and this clearly shows what that block of code does. Probably true, but if I sometimes forget to do the last assignment self.myView.frame = frame; I think I’d forget even more that last frame; line.
  • The stack variables (frame, button, etc.) don’t mess with other code in the same method, so it’s possible to reuse same names again and again. Totally true, that’s the part I like the most, I often need to use frameView, frameButton and so on (or similar with number suffixes or whatever).
  • It kinds of encapsulate some standalone functionality in a single block of code. That’s also great actually.

To be fair I haven’t decided yet if I’m going to make use of this construction, maybe I’ll give it a try.


Code not compiling when using blocks inside a switch statement

Totally unrelated, some months ago I had compiling problems with a quite simple code and drove me nuts for a while. I started with something trivial like this:

switch(i) {
    case 1:
        NSLog(@"Case 1");
        break;
    case 2:
        NSLog(@"Case 2");
        break;
    case 3:
        NSLog(@"Case 3");
        break;
    default:
        NSLog(@"Case whatever else"); 
        break;
}

This, of course, compiles and executes perfectly. But my code was just slightly more complex and use methods with blocks in some of the switch cases, like this:

switch(i) { 
    case 1:
        NSLog(@"Case 1");
        break;
    case 2:
        NSLog(@"Case 2");
        [UIView animateWithDuration:1.0
                         animations:^{
                             self.myView.frame = someFrame;
                         }];
        break;
    case 3:
        NSLog(@"Case 3");
        break; 
    default:
        NSLog(@"Case whatever else"); 
        break;
}

And this suddenly didn’t compile. It shows an error message saying “Switch case is in protected scope”. It seems the problem is the compiler doesn’t know how to properly scope that block and its content. To solve this problem I only had to add some extra braces to explicitly scope the code inside the case:

switch(i) { 
    case 1:
        NSLog(@"Case 1");
        break;
    case 2: { // '{' to start scoped block
        NSLog(@"Case 2");
        [UIView animateWithDuration:1.0
                         animations:^{
                             self.myView.frame = someFrame;
                         }];
        } // '}' to end scoped block
        break;
    case 3:
        NSLog(@"Case 3");
        break; 
    default:
        NSLog(@"Case whatever else"); 
        break;
}

The brace closing the scoped block can be at the end of previous line, of course, I just didn’t put it there in this example to make it clearer.