Is it necessary to use weak references to self always inside blocks..?

前端 未结 2 483
独厮守ぢ
独厮守ぢ 2020-12-12 13:15

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

相关标签:
2条回答
  • 2020-12-12 13:30

    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.

    0 讨论(0)
  • 2020-12-12 13:45

    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.

    0 讨论(0)
提交回复
热议问题