169

I'm afraid this question is pretty basic, but I think it's relevant to a lot of Objective-C programmers who are getting into blocks.

What I've heard is that since blocks capture local variables referenced within them as const copies, using self within a block can result in a retain cycle, should that block be copied. So, we are supposed to use __block to force the block to deal directly with self instead of having it copied.

__block typeof(self) bself = self;
[someObject messageWithBlock:^{ [bself doSomething]; }];

instead of just

[someObject messageWithBlock:^{ [self doSomething]; }];

What I'd like to know is the following: if this is true, is there a way that I can avoid the ugliness (aside from using GC)?

Jonathan Sterling
  • 18,320
  • 12
  • 67
  • 79
  • 3
    I like to call my `self` proxies `this` just to flip things around. In JavaScript I call my `this` closures `self`, so it feels nice and balanced. :) – devios1 Jul 30 '13 at 22:43
  • I wonder is there any equivalent action needs to be done if I am using Swift blocks – Ben Lu Nov 18 '15 at 20:48
  • @BenLu absolutely! in Swift closures (and functions which get passed around that mention self implicitly or explicitly) will retain self. Sometimes this is desired, and other times it creates a cycle (because the closure itself gets owned by the self (or owned by something self owns). The main reason this happens is because of ARC. – Ethan Apr 29 '16 at 14:11
  • 1
    To avoid problems, the appropriate way to define 'self' to be used in a block is '__typeof(self) __weak weakSelf = self;' in order to have a weak reference. – XLE_22 Apr 01 '17 at 16:29

9 Answers9

172

Strictly speaking, the fact that it's a const copy has nothing to do with this problem. Blocks will retain any obj-c values that are captured when they are created. It just so happens that the workaround for the const-copy issue is identical to the workaround for the retain issue; namely, using the __block storage class for the variable.

In any case, to answer your question, there's no real alternative here. If you're designing your own block-based API, and it makes sense to do so, you could have the block get passed the value of self in as an argument. Unfortunately, this doesn't make sense for most APIs.

Please note that referencing an ivar has the exact same issue. If you need to reference an ivar in your block, either use a property instead or use bself->ivar.


Addendum: When compiling as ARC, __block no longer breaks retain cycles. If you're compiling for ARC, you need to use __weak or __unsafe_unretained instead.

Lily Ballard
  • 182,031
  • 33
  • 381
  • 347
  • No problem! If this answered the question to your satisfaction, I would appreciate it if you could choose this as the correct answer to your question. If not, please let me know how I can answer your question better. – Lily Ballard Dec 04 '10 at 08:24
  • 4
    No problem, Kevin. SO delays you from selecting an answer to a question immediately, so I had to come back a little later. Cheers. – Jonathan Sterling Dec 04 '10 at 08:47
  • __unsafe_unretained id bself = self; – caleb Apr 27 '12 at 16:47
  • @caleb: Or if you want to preserve the type of self, you can use `__unsafe_unretained __typeof__(self) bself = self;` – Lily Ballard Apr 27 '12 at 17:04
  • @KevinBallard: Actually, if I do that, I get an error saying that self "already has retainment attributes set on it" (__strong). – caleb Apr 27 '12 at 17:20
  • @caleb: Oh that's interesting. I didn't expect `__typeof__(self)` to include the retainment attribute. Must be an ARC-specific thing. – Lily Ballard Apr 27 '12 at 18:47
  • Isn't `__weak` the correct ARC way of doing this, not `__unsafe_unretained`? (Assuming you're using ARC in Lion or iOS 5.) – JK Laiho Jun 27 '12 at 08:25
  • 4
    @JKLaiho: Sure, `__weak` is fine as well. If you know for a fact that the object cannot be out of scope when the block is invoked then `__unsafe_unretained` is ever so slightly faster, but in general that won't make a difference. If you do use `__weak`, make sure to throw it into a `__strong` local variable and test that for non-`nil` before doing anything with it. – Lily Ballard Jun 27 '12 at 18:07
  • 2
    @Rpranata: Yes. `__block`'s side-effect of not retaining and releasing was purely due to the inability to properly reason about that. With ARC, the compiler gained that ability, and so `__block` now retains and releases. If you need to avoid that, you need to use `__unsafe_unretained`, which instructs the compiler to not perform any retains or releases on the value in the variable. – Lily Ballard Sep 03 '12 at 21:13
  • Is there a reason Xcode 5.1 with iOS7 SDK still recommends __block to break the retain cycle when the object is modified inside the block? I am still a little confused on this matter after reading a billion and one SO and blog entries on it. – chadbag Apr 18 '14 at 23:08
  • @chadbag: I'm mildly confused. You can't modify non-`__block` captured variables inside a block. And Xcode's retain cycle detection doesn't care about whether you modify the variables, only whether you capture them. But in any case, in non-ARC code, `__block` is still the correct way to avoid the retain on the captured object. – Lily Ballard Apr 20 '14 at 15:31
  • @Kevin Ballard : No, I am the one that is confused :). I need to go and look at where Xcode has encouraged me to use __block. All my code where this is concerned is ARC. – chadbag Apr 21 '14 at 15:35
  • I don't understand the problem with retain cycles in this case, I mean, when the block finishes, it'll release the 'self', right? So the parent will get back to 1 or whatever, and the block will already be dead. – noripcord Jul 28 '14 at 00:16
  • @no_ripcord: The block will release `self` when the block itself is deallocated, not when it finishes executing. If the block is (directly or indirectly) retained by `self`, and there's nothing that explicitly breaks the cycle, then both `self` and the block will keep each other alive indefinitely. – Lily Ballard Jul 29 '14 at 01:02
  • @KevinBallard In the OP's example, is there a case where the block might be (directly or indirectly) retained by `self`? I am under the assumption that the block can only be retained by `self` if it was stored as a `strong` property in `self` (which doesn't look like the case here). Are there any other ways where `self` may retain the block (directly or indirectly)? – ken Oct 07 '14 at 05:49
  • so what if I don't use iVar but underscore , do I get ride of the referencing problem? – Chen Xiaofeng Dec 08 '14 at 17:11
69

Just use:

__weak id weakSelf = self;

[someObject someMethodWithBlock:^{
    [weakSelf someOtherMethod];
}];

For more information: WWDC 2011 - Blocks and Grand Central Dispatch in Practice.

https://developer.apple.com/videos/wwdc/2011/?id=308

Note: if that doesn't work you can try

__weak typeof(self)weakSelf = self;
3lvis
  • 4,190
  • 1
  • 30
  • 35
  • 2
    And did you by any chance found it :)? – Tieme Jan 18 '13 at 15:44
  • 2
    You can check the video here - https://developer.apple.com/videos/wwdc/2011/#blocks-and-grand-central-dispatch-in-practice – nswamy Jun 03 '13 at 10:18
  • Are you able to reference self inside "someOtherMethod"? Would self reference the weakself at that point or would that also create a retain cycle? – Oren Mar 19 '15 at 01:39
  • Hi @Oren, if you try to reference self inside "someOtherMethod" you would get a Xcode warning. My approach just makes a weak reference of self. – 3lvis Mar 19 '15 at 09:05
  • 1
    I only got a warning when referencing self directly inside the block. Putting self inside someOtherMethod didn't cause any warnings. Is that because xcode isn't smart enough or is it not an issue? Would referencing self inside someOtherMethod refer to weakSelf already since that's what your'e calling the method on? – Oren Mar 19 '15 at 16:22
  • In the example above, the block uses a weak pointer to self. It uses that to invoke a method in self, unless weakSelf is nil. if `weakSelf` is nil, the code `[weakSelf someOtherMethod]` tries to send a message to nil, which is a no-op in Objective-C. Once you're inside the instance method `someOtherMethod`, you have a `self` pointer that refers to the object that received the message. – Duncan C Jan 23 '18 at 21:20
  • The whole point of using weakSelf, is to let it be nil, if the block is executed AFTER self was released. instead of 'self' retaining the block, which in turn retains 'self' thus creating a memory cycle - only self retains the block, and the block only receives a weak reference to 'self'. one that can nullify automatically when block actually runs. – Motti Shneor Jul 01 '19 at 15:56
25

This might be obvious, but you only have to do the ugly self alias when you know you’ll get a retain cycle. If the block is just a one-shot thing then I think you can safely ignore the retain on self. The bad case is when you have the block as a callback interface, for example. Like here:

typedef void (^BufferCallback)(FullBuffer* buffer);

@interface AudioProcessor : NSObject {…}
@property(copy) BufferCallback bufferHandler;
@end

@implementation AudioProcessor

- (id) init {
    …
    [self setBufferCallback:^(FullBuffer* buffer) {
        [self whatever];
    }];
    …
}

Here the API does not make much sense, but it would make sense when communicating with a superclass, for example. We retain the buffer handler, the buffer handler retains us. Compare with something like this:

typedef void (^Callback)(void);

@interface VideoEncoder : NSObject {…}
- (void) encodeVideoAndCall: (Callback) block;
@end

@interface Foo : NSObject {…}
@property(retain) VideoEncoder *encoder;
@end

@implementation Foo
- (void) somewhere {
    [encoder encodeVideoAndCall:^{
        [self doSomething];
    }];
}

In these situations I don’t do the self aliasing. You do get a retain cycle, but the operation is short-lived and the block will get out of memory eventually, breaking the cycle. But my experience with blocks is very small and it might be that self aliasing comes out as a best practice in the long run.

zoul
  • 102,279
  • 44
  • 260
  • 354
  • 6
    Good point. It's only a retain cycle if self is keeping the block alive. In the case of blocks that never get copied, or blocks with a guaranteed limited duration (e.g. the completion block for a UIView animation), you don't have to worry about it. – Lily Ballard Dec 04 '10 at 08:47
  • 6
    In principle, you're correct. However, if you were to execute the code in the example, you'd crash. Block properties should *always* be declared as `copy`, not `retain`. If they're just `retain`, then there's no guarantee they'll get moved off the stack, which means when you go to execute it, it won't be there anymore. (and copying and already-copied block is optimized to a retain) – Dave DeLong Dec 04 '10 at 09:01
  • Ah, sure, a typo. I went through the `retain` phase a while ago and quickly realized the thing you are saying :) Thanks! – zoul Dec 04 '10 at 09:03
  • I'm pretty sure `retain` is completely ignored for blocks (unless they've already moved off the stack with `copy`). – Steven Fisher Mar 01 '12 at 04:28
  • @Dave DeLong, No, it would not crash since the @property(retain) is used for an object reference only, not the block.. There is no need for a copy to be used here at all.. – DeniziOS Jan 12 '13 at 05:50
20

Posting another answer because this was a problem for me too. I originally thought I had to use blockSelf anywhere there was a self reference inside a block. This is not the case, it is only when the object itself has a block in it. And in fact, if you use blockSelf in these cases the object can get dealloc'd before you get the result back from the block and then it will crash when it tries to call it, so clearly you want self to be retained until the response comes back.

First case demonstrates when a retain cycle will occur because it contains a block which is referenced in the block:

#import <Foundation/Foundation.h>

typedef void (^MyBlock)(void);

@interface ContainsBlock : NSObject 

@property (nonatomic, copy) MyBlock block;

- (void)callblock;

@end 

@implementation ContainsBlock
@synthesize block = _block;

- (id)init {
    if ((self = [super init])) {

        //__block ContainsBlock *blockSelf = self; // to fix use this.
        self.block = ^{
                NSLog(@"object is %@", self); // self retain cycle
            };
    }
    return self;
}

- (void)dealloc {
    self.block = nil;
    NSLog (@"ContainsBlock"); // never called.
    [super dealloc];
} 

- (void)callblock {
    self.block();
} 

@end 

 int main() {
    ContainsBlock *leaks = [[ContainsBlock alloc] init];
    [leaks callblock];
    [leaks release];
}

You don't need blockSelf in the second case because the calling object does not have a block in it that will cause a retain cycle when you reference self:

#import <Foundation/Foundation.h>

typedef void (^MyBlock)(void);

@interface BlockCallingObject : NSObject 
@property (copy, nonatomic) MyBlock block;
@end

@implementation BlockCallingObject 
@synthesize block = _block;

- (void)dealloc {
    self.block = nil;
    NSLog(@"BlockCallingObject dealloc");
    [super dealloc];
} 

- (void)callblock {
    self.block();
} 
@end

@interface ObjectCallingBlockCallingObject : NSObject 
@end

@implementation ObjectCallingBlockCallingObject 

- (void)doneblock {
    NSLog(@"block call complete");
}

- (void)dealloc {
    NSLog(@"ObjectCallingBlockCallingObject dealloc");
    [super dealloc];
} 

- (id)init {
    if ((self = [super init])) {

        BlockCallingObject *myobj = [[BlockCallingObject alloc] init];
        myobj.block = ^() {
            [self doneblock]; // block in different object than this object, no retain cycle
        };
        [myobj callblock];
        [myobj release];
    }
    return self;
}
@end

int main() {

    ObjectCallingBlockCallingObject *myObj = [[ObjectCallingBlockCallingObject alloc] init];
    [myObj release];

    return 0;
} 
possen
  • 8,596
  • 2
  • 39
  • 48
  • That's a common misconception and can be dangerous, because blocks that *should* retain `self` may not due to people over-applying this fix. This is a good example of avoiding retain cycles in non-ARC code, thanks for posting. – Carl Veazey Feb 15 '13 at 10:47
9

Remember also that retain cycles can occur if your block refers to another object which then retains self.

I'm not sure that Garbage Collection can help in these retain cycles. If the object retaining the block (which I'll call the server object) outlives self (the client object), the reference to self inside the block will not be considered cyclic until the retaining object itself is released. If the server object far outlives its clients, you may have a significant memory leak.

Since there are no clean solutions, I would recommend the following workarounds. Feel free to choose one or more of them to fix your issue.

  • Use blocks only for completion, and not for open-ended events. For example, use blocks for methods like doSomethingAndWhenDoneExecuteThisBlock:, and not methods like setNotificationHandlerBlock:. Blocks used for completion have definite ends of lives, and should be released by server objects after they are evaluated. This prevents the retain cycle from living for too long even if it occurs.
  • Do that weak-reference dance you described.
  • Provide a method to clean up your object before it's released, which "disconnects" the object from server objects that may hold references to it; and call this method before calling release on the object. While this method is perfectly fine if your object only has one client (or is a singleton within some context), but will break down if it has multiple clients. You're basically defeating the retain-counting mechanism here; this is akin to calling dealloc instead of release.

If you are writing a server object, take block arguments only for completion. Do not accept block arguments for callbacks, such as setEventHandlerBlock:. Instead, fall back to the classic delegate pattern: create a formal protocol, and advertise a setEventDelegate: method. Do not retain the delegate. If you don't even want to create a formal protocol, accept a selector as a delegate callback.

And lastly, this pattern should ring alarms:

- (void)dealloc {
    [myServerObject releaseCallbackBlocksForObject:self];
    ...
}

If you're trying to unhook blocks that may refer to self from inside dealloc, you're already in trouble. dealloc may never be called due to the retain cycle caused by references in the block, which means that your object is simply going to leak until the server object is deallocated.

Dave R
  • 605
  • 3
  • 5
  • GC does help if you use `__weak` appropriately. – tc. Feb 16 '12 at 16:23
  • Tracing garbage collection can of course deal with retain cycles. Retain cycles is only a problem for reference counting environments – newacct Oct 16 '12 at 01:43
  • Just so everybody knows, garbage collection was deprecated in OS X v10.8 in favour of Automatic Reference Counting (ARC) and is scheduled to be removed in a future version of OS X (http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html). – Ricardo Sanchez-Saez Feb 13 '13 at 14:44
1

__block __unsafe_unretained modifiers suggested in Kevin's post may cause to the bad access exception in case of block executed in a different thread. It's better use only __block modifier for the temp variable and make it nil after the usage.

__block SomeType* this = self;
[someObject messageWithBlock:^{
  [this doSomething]; // here would be BAD_ACCESS in case of __unsafe_unretained with
                      //  multithreading and self was already released
  this = nil;
}];
Community
  • 1
  • 1
b1gbr0
  • 11
  • 1
  • Wouldn't be really safer to just use __weak instead of __block to avoid the need of nilling the variable after using it? I mean, this solution is great if you want to break other types of cycles but certainly I don't see any particular advantages for "self" retain cycles on it. – Alejandro Benito-Santos Nov 28 '12 at 13:09
  • You can't use __weak if your platform target is iOS 4.x. Also sometimes you need that the code in the block has been executed for the valid object, not for nil. – b1gbr0 Nov 28 '12 at 13:47
1

You can use libextobjc library. It is quite popular, it is used in ReactiveCocoa for example. https://github.com/jspahrsummers/libextobjc

It provides 2 macros @weakify and @strongify, so you can have:

@weakify(self)
[someObject messageWithBlock:^{
   @strongify(self)
   [self doSomething]; 
}];

This prevents a direct strong reference so we don't get into a retain cycle to self. And also, it prevents self from becoming nil half-way, but still properly decrements the retain count. More in this link: http://aceontech.com/objc/ios/2014/01/10/weakify-a-more-elegant-solution-to-weakself.html

Yuri Solodkin
  • 530
  • 8
  • 26
  • 1
    Before showing the simplified code it would be better to know whats behind it, everybody should know the real two lines of code. – Alex Cio Feb 23 '15 at 23:56
0

How about this?

- (void) foo {
     __weak __block me = self;

     myBlock = ^ {
        [[me someProp] someMessage];
     }
     ...
 }

I don't get the the compiler warning anymore.

Καrτhικ
  • 3,833
  • 2
  • 29
  • 42
-1

Block: a retain cycle will occur because it contains a block which is referenced in the block; If you make the block copy and use a member variable,self will retain.

yijiankaka
  • 128
  • 3