Question

This is for learning =) I understand functions, methods and blocks can all be declared and then called. I'm just trying to understand blocks better.

This is a basic idea of what I want to do.

CGRectMake(100,^CGFloat(){return 1.0f;},100,100);

The compiler is not seeing the return value of the block and is instead seeing the block itself as the value which results in an error. I tried a few ways of casting the block but was unable to figure out a solution.

Is there a way to do this and if so how? If not is there another way to do an inline function with a return value?

Edit Heres a code example I'm using based on the correct answers first example.

valueLabelMin.frame = CGRectMake(0,
                                 ^CGFloat(){
                                   if (CGRectGetMaxY(dateRangeStartLabel.frame)) {
                                     return CGRectGetMaxY(dateRangeStartLabel.frame)-20;
                                   }else{
                                     return self.bounds.size.height-20;
                                   }
                                 }(),
                                 50,
                                 20);

Edit 2 This goes a little out of the context of the original question but demonstrates its relevance in a context which I always appreciate when reading questions.

This example code changes the frame of some UILabels based on conditions, is optionally animated and executes a completion block.

Notice that each labels setFrame is called only once resulting in very manageable code =D Needles to say, the "before" version was such a mess I can't bring myself to include it.

- (void)updateValueRangeLabels:(BOOL)animated completion:(void(^)(void))completion {

    void (^setLabelFrames)() = ^()
    {
        valueLabelMax.frame = CGRectMake(^CGFloat(){if(_showValueRange){return 0;}else{return -50;}}(),
                                         CGRectGetMaxY(titleLabel.frame),
                                         50, 20);

        valueLabelMid.frame = CGRectMake(^CGFloat(){if(_showValueRange){return 0;}else{return -50;}}(),
                                         CGRectGetMaxY(titleLabel.frame) + (self.bounds.size.height - CGRectGetMaxY(titleLabel.frame) - CGRectGetMinY(dateRangeStartLabel.frame) - 20)/2,
                                         50, 20);

        valueLabelMin.frame = CGRectMake(^CGFloat(){if(_showValueRange){return 0;}else{return -50;}}(),
                                         ^CGFloat(){if(_showDateRange){return CGRectGetMinY(dateRangeStartLabel.frame)-20;}else{return self.bounds.size.height - 20;}}(),
                                         50, 20);
    };

    if (animated) {
        [UIView animateWithDuration:0.3 animations:^{
            setLabelFrames();
        }completion:^(BOOL finished){
            completion();
        }];
    }else{
        setLabelFrames();
        completion();
    }
}

Blocks are amazing!

Was it helpful?

Solution

Evaluate it, like so:

CGRect r = CGRectMake(100,^CGFloat(){return 1.0f;}(),100,100);
                                                  ^^

Another example, introducing a parameter:

// creates a CGRect with all values set to the parameter (12 in this example)
CGRect r = ^CGRect(CGFloat p){return (CGRect){p,p,p,p};}(12);

OTHER TIPS

Plain

CGRect frame = view.frame;
frame.origin.x = 12;
view.frame = frame:

Parantheses

view.frame = (CGRect frame = view.frame; frame.origin.x = 12; frame);

Block

view.frame = ^{CGRect frame = view.frame; frame.origin.x = 12; return frame; }();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top