42

I am getting confused with use of self inside blocks, I go through some of Apple's documents but still cannot find the right answer.

Some people always say use weak self inside blocks, but some say use weak self in blocks that are copied, not neassary to use always.

Sample 1:

self.handler = ^(id response, NSError *error)
{
    self.newresponse = response; //use weak self here
};  

Sample 2:

Using weak self;

__weak myViewController *weakSelf = self;

[UIView animateWithDuration:interval delay:0.0 options:curve animations:^
{
    [weakSelf.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)];
    //in above is it use of weak is neassary 
}
completion:^(BOOL finished)
{

}];

Without weak self;

__weak myViewController *weakSelf = self;

[UIView animateWithDuration:interval delay:0.0 options:curve animations:^
{
    [myViewController.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)];

}
completion:^(BOOL finished)
{

}];

In the above samples, which are correct…? **I am using ARC

ShivaPrasad
  • 915
  • 1
  • 11
  • 22
  • possible duplicate of [Possible to pass \[self anyFunction\] in blocks without \_\_weak object (iOS 5 + ARC)](http://stackoverflow.com/questions/9003600/possible-to-pass-self-anyfunction-in-blocks-without-weak-object-ios-5-arc) – Abizern Nov 02 '12 at 12:01
  • Also a duplicate of http://stackoverflow.com/questions/20030873/always-pass-weak-reference-of-self-into-block-in-arc – Rose Perrone Apr 05 '15 at 18:29

2 Answers2

76

You should only use a weak reference to self, if self will hold on to a reference of the block.

In your example, you are not keeping a reference to your block in self, you are only using blocks inline with the UIView animateWithDuration:, and as such there is no need to use __weak myViewController *weakSelf = self;

Why is this the case? Because a block will retain strong references to any variables it uses from the class using the block. This includes self. Now if the class instance itself keeps a strong reference to the block, and the block keeps a strong reference to the class instance, you have a retain cycle, which will cause memory leaks.

WDUK
  • 18,870
  • 3
  • 64
  • 72
  • 3
    so in class method (animateWithDuration) no need of weak self since self is not retaining or owning that block am i right...? – ShivaPrasad Nov 02 '12 at 12:16
  • In sample 1 self.handler = ^(id response, NSError *error) { self.newresponse = response; //use weak self here }; we need week self since block is retain by self and self is retain by block so it is retain cycles...? – ShivaPrasad Nov 02 '12 at 12:17
  • 5
    @jeeva In Sample 1, a weak reference to self **is** needed. In samples 2 and 3, a weak reference to self **is not** needed. – WDUK Nov 02 '12 at 12:22
  • 2
    Thanks, your explanation totally makes sense. However, I can't explain the use of `weakSelf` in this sample code from Apple: http://developer.apple.com/library/ios/#documentation/AddressBook/Reference/ABAddressBookRef_iPhoneOS/Reference/reference.html%23//apple_ref/doc/uid/TP40007099-CH991-SW4 – Ortwin Gentz Jan 09 '13 at 14:26
  • It need a weak reference because the block is using a property belonging to self (`weakSelf.numberOfSmiths`). If you're accessing a property on an object, then this will retain the object to make sure the property is still accessible when the block runs. – WDUK Jan 09 '13 at 16:46
  • I still don't fully understand it. If it used self.numberOfSmiths it still shouldn't cause a retain cycle. self doesn't have a reference to the block. – mlaster Jul 20 '13 at 19:42
  • 1
    A good point, I missed the fact that `self` is not retaining the block; it's simply a callback for the framework. Apologies. I believe in this case, it's a form of defensive coding. There's no harm in declaring it weak, as conceptually it doesn't make sense to retain `self` here (why should a callback extend the life of `self`?). It also means if someone wanted to store the block later on, they don't need to change its contents. Ultimately, whilst declaring it weak here isn't *required* to prevent leaks, it's a style some programmers take to ensure robustness. – WDUK Jul 21 '13 at 23:29
  • Is it needed to use a weak reference for `self` if we are calling methods in it only ? Say `myblock {[self removeLoadingIcon];}` ? – GoodSp33d Nov 24 '13 at 08:04
  • @WDUK what if the animation block runs infinitely ? – onmyway133 Feb 12 '15 at 05:25
  • @WDUK what if (because the animation block is a delayed operation) self is deallocated when block runs? – Stas Feb 01 '16 at 17:09
  • ```You should only use a weak reference to self, if self will hold on to a reference of the block.``` What if you are animating a UIKit element in a block but your view is released? You don't want to keep a strong reference to just animate something that it's not in the view anymore, so in that case it would make sense to use `weak` as well, even if there is no retain cycle. – Pablo A. Aug 31 '16 at 13:31
10

Here's some code that demonstrates @WDUK's answer:

typedef void (^SimpleBlock)();

@interface ObjectThatRetainsBlock : NSObject
@property(nonatomic, strong) SimpleBlock block;
@end

@implementation ObjectThatRetainsBlock

- (instancetype)init {
  self = [super init];
  if (self) {
    self.block = ^{ NSLog(@"Running block in %@", self); };
    self.block();
  }
  return self;
}

- (void)dealloc {
  NSLog(@"ObjectThatRetainsBlock is deallocated.");
}

@end

@interface ObjectThatDoesNotRetainBlock : NSObject
@end

@implementation ObjectThatDoesNotRetainBlock

- (instancetype)init {
  self = [super init];
  if (self) {
    SimpleBlock block = ^{ NSLog(@"Running block in %@", self); };
    block();
  }
  return self;
}

- (void)dealloc {
  NSLog(@"ObjectThatDoesNotRetainBlock is deallocated.");
}

@end

- (void)test {
  ObjectThatRetainsBlock *objectThatRetainsBlock =
      [[ObjectThatRetainsBlock alloc] init];
  ObjectThatDoesNotRetainBlock *objectThatDoesNotRetainBlock = 
      [[ObjectThatDoesNotRetainBlock alloc] init];
}

The test method prints:

Running block in <ObjectThatRetainsBlock: 0x7f95f3335e50>
Running block in <ObjectThatDoesNotRetainBlock: 0x7f95f3335c50>
ObjectThatDoesNotRetainBlock is deallocated.

Observe that in the init method of ObjectThatDoesNotRetainBlock, we create block as an ivar, but when the block goes out of scope, we don't keep a reference to it.

In the test method, when the two objects go out of scope, observe that objectThatDoesNotRetainBlock is deallocated because it is not part of a retain cycle.

On the other hand, objectThatRetainsBlock does not get deallocated, because it is part of a retain cycle. It retains the block beyond the scope of the method call.

If you want an another explanation, see this answer.

Community
  • 1
  • 1
Rose Perrone
  • 61,572
  • 58
  • 208
  • 243