jsd
jsd

Reputation: 7703

Block that can access self and be used throughout an instance

I want a block that is available throughout a class, so it can be re-used many times by different methods in the instance.

I want that block to be able to reference self.

I want to not have the block create any nasty retain cycles by retaining self.

So far I am stumped. I managed to create block in the .m outside of any method definitions, and that got me partway - I could reuse the block everywhere, but I couldn't access self. I tried putting the block into an ivar but I'm doing something wrong there and now I'm getting random EXC_BAD_ACCESS. Can someone explain it simply, line by line?

Upvotes: 3

Views: 932

Answers (3)

jsd
jsd

Reputation: 7703

I figured it out.

In MyClass.h:

typedef void (^DefaultFailureBlock)();

@property (copy) DefaultFailureBlock defaultFailureBlock;

in the init method:

__block MyClass *selfReq = self;
self.defaultFailureBlock = ^{
    //use selfReq instead of self in here.
};

Interestingly, if you accidentally refer to self inside the block, you will have a retain cycle, and Analyze will not complain. I put an NSLog in dealloc to prove that it is actually being dealloced, and it is.

Oh and don't forget to [defaultFailureBlock release]; in dealloc too...

Upvotes: 0

Jano
Jano

Reputation: 63667

This idiom may help you to remove the exc_bad_access (ARC code).

// get a weak reference to self
__weak id weakSelf = self;
block = ^()
{
    // now the block is executing so we get a strong reference to self
    // (this prevents self from disappearing until the block is done executing)
    id strongSelf = weakSelf;
    if (strongSelf != nil)
    {
        // do whatever work you intended for this block
    }
};

Upvotes: 1

Krizz
Krizz

Reputation: 11542

Try the following:

typedef void (^MyBlock)();

@implementation MyClass
{
    MyBlock block;
}

- (id) init
{
   self = [super init];
   if (!self)
      return nil;

   __block MyClass* _self = self;

   block = [^ {
       [_self sendSomeMsg];
   } copy];
}

Note the __block storage type. Quoting this: "At function level are __block variables. These are mutable within the block (and the enclosing scope) and are preserved if any referencing block is copied to the heap."

Upvotes: 1

Related Questions