3

I have an NSUInteger defined as a property like so:

@property (nonatomic, assign) NSUInteger wordDisplayed;

I need to have this as a property because I need access to read/write to this variable from other methods and classes.

When trying to change the value of this property within a block, I get the following warning:

Capturing 'self' strongly in this block is likely to lead to a retain cycle

"Block will be retained by an object strongly retained by the captured object"

How can I update this variable property within a block?

The block I'm using is in a modified UIActionSheet that I'm using to make the UIActionSheet accept blocks.

https://github.com/zoul/Lambda-Alert

Here is an example of my code:

 sectionHeadersAct = [[LambdaSheet alloc] initWithTitle:@"Book 2 Lesson 1"];
    [sectionHeadersAct addButtonWithTitle:@"D. E. F. & G. Teach New Letters" block:^{ 
        wordDisplayed = 15; //This is where I'm trying to change the value
    }];

[sectionHeadersAct showInView:self.view];
Jason
  • 171
  • 1
  • 11
  • Similar question to http://stackoverflow.com/questions/8159274/ios-5-twitter-framework-completionhandler-block-capturing-self-strongly-i – JiaYow Feb 22 '12 at 00:26

2 Answers2

4

This post deals with this certain issue: https://stackoverflow.com/a/8159567/656036

To summarize it: You should use a weak pointer to self. If you use ARC, you can solve this by writing this before your block:

__weak MyObject *weakSelf = self;

And using weakSelf instead of self in the block itself.

EDIT Try this:

__weak ViewController *weakSelf = self;
sectionHeadersAct = [[LambdaSheet alloc] initWithTitle:@"Book 2 Lesson 1"];
[sectionHeadersAct addButtonWithTitle:@"D. E. F. & G. Teach New Letters" block:^{ 
    weakSelf.wordDisplayed = 15;
}];

[sectionHeadersAct showInView:self.view];
Community
  • 1
  • 1
fscheidl
  • 2,281
  • 3
  • 19
  • 33
  • What `self` represents. Often a `UIViewController` class. Updated the class name in my post. – fscheidl Feb 22 '12 at 00:46
  • 1
    Thank you!! This worked, and I learned something new. The object was a UIViewController, but using UIViewController did not work. I replaced UIViewController with the name of the class I was in. "MainViewController" and that worked. Thanks again! :) – Jason Feb 22 '12 at 00:50
3

This is a common occurrence when using blocks. I assume you are accessing the property with the block by something like self.wordDispalyed.

Because blocks can be run asynchronously, they hold a strong reference to objects inside them. This is so that if they run at some time after you have released the object, at least the block can still send messages to it.

In your case, you are referencing a property within the block. So the block retains the the object, in this case self. But, your object (the self) is also retaining the block, since it has to run it. So you have a circular reference. The block retains the object, and the object retains the block. This might cause you problems - and the compiler is warning you of this.

To get around this you need to create a local variable that well be retained by the block, and use that to reference the property. It's a simple as writing:

__weak TheObject *blockSelf = self;

And then within your block you deal with the property as:

blockSelf.wordDisplayed …
Abizern
  • 146,289
  • 39
  • 203
  • 257