Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling [self methodName] from inside a block?

I've just run into blocks and I think they are just what I'm looking for, except for one thing: is it possible to call a method [self methodName] from within a block?

This is what I'm trying to do:

-(void)someFunction{
    Fader* fader = [[Fader alloc]init];

    void (^tempFunction)(void) = ^ {
        [self changeWindow:game]; 
        //changeWindow function is located in superclass
    };

    [fader setFunction:tempFunction];
}

I've been searching for a couple of days and I can't find any evidence that this is possible.

Is this at all possible, or am I trying to use blocks for something they aren't meant for?

The reason I'm using blocks is that I've created a Fader class, and I want to store a block for it to execute when it finishes fading out.

Thank you

EDIT: Okay, I added in the suggestion, but I'm still getting an EXC_BAD_ACCESS error...

-(void)someFunction{
    Fader* fader = [[Fader alloc]init];

    __block MyScreen* me = self;

    void (^tempFunction)(void) = ^ {
        [me changeWindow:game]; 
        //changeWindow function is located in superclass
    };

    [fader setFunction:tempFunction];
    [fader release];
}

Maybe I'm not allowed to give fader the function...?

like image 299
Marty Avatar asked Feb 16 '11 23:02

Marty


4 Answers

Yes, you can do this.

Note, however, that the block will retain self. If you end up storing this block in an ivar, you could easily create a retain cycle, which means neither would ever get deallocated.

To get around this, you can do:

- (void) someMethodWithAParameter:(id)aParameter {

  __block MySelfType *blocksafeSelf = self;
  void (^tempFunction)(void) = ^ {
      [blocksafeSelf changeWindow:game];
  };

  [self doSomethingWithBlock:tempFunction];

}

The __block keyword means (among other things) that the referenced object will not be retained.

like image 92
Dave DeLong Avatar answered Nov 18 '22 05:11

Dave DeLong


The accepted answer is outdated. Using __block in that case can cause errors!

To avoid this problem, it’s best practice to capture a weak reference to self, like this:

- (void)configureBlock {
    XYZBlockKeeper * __weak weakSelf = self;
    self.block = ^{
        [weakSelf doSomething];   // capture the weak reference
                                  // to avoid the reference cycle
    }
}

Please, look at Apple Documentation - Avoid Strong Reference Cycles when Capturing self for more details.

like image 27
skywinder Avatar answered Nov 18 '22 04:11

skywinder


__block CURRENTViewController *blocksafeSelf = self;

[homeHelper setRestAsCheckIn:strRestId :^(NSObject *temp) {
    [blocksafeSelf YOURMETHOD:params];
}];
like image 3
Ketan Patel Avatar answered Nov 18 '22 04:11

Ketan Patel


Is it possible to call a method [self methodName] from within a block?

Yes, why not. If your tempFunction is an instance method, you can do it. The called method should be accessible is the only restriction.

like image 1
Mahesh Avatar answered Nov 18 '22 03:11

Mahesh