Do I need to use a weak self pointer if a method called from a Block uses self?

后端 未结 4 675
悲&欢浪女
悲&欢浪女 2021-01-15 14:46

Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this

BUT!

If from my block I

4条回答
  •  抹茶落季
    2021-01-15 15:41

    Short answer: no, in this situation self is not retained.

    Long answer

    First of all, retaining self and a reference cycle are not the same thing. Reference cycle is a cycle of strong references between a number of objects: A->B->C->A is a retain cycle.

    The general idea is, you want to always guarantee that if you are referencing self in a block, you don't reference this block strongly, and don't reference it through a chain of strong references. In reality, retain cycles can be used purposefully if you are making sure you're breaking the retain cycle under certain conditions. Not that I personally recommend this.

    Take a look at documentation on Apple's website. It clearly states that values are captured in blocks, and capturing an object reference retains this object in block.

    Basically what this means is that referencing an object in a block increments its retainCount by 1, and when this block gets deallocated, retainCount is decremented by 1.

    However, when using a __weak pointer in a block, the retain count is untouched.

    Here's an example:

    - (void) doSomething {
       NSLog(@"%@", self);
    }
    
    - (void) callBlock {
       __weak typeof(self) weakSelf = self;
       dispatch_block_t block = ^{
          [weakSelf doSomething];
       };
    }
    

    When you write [obj method:params] this actually translates into following call: objc_msgSend(obj, @selector(method:), params). One of the features of Objective-C is that if you call a method on nil pointer, it returns nil. This is guaranteed by the fact that objc_msgSend(nil, @selector(anyselector), ...) always return nil. Note that SEL is just a const char[] under the covers, so it doesn't affect retain counts by any means.

    Hence when the block will be executed, if your object was deallocated, the weak weakSelf variable will be nullified, and the block's body will translate into objc_msgSending to zero, which does nothing except of wasting few CPU cycles.

    To sum it up, the Objective-C messaging system is implemented in such a way that calling a method does not retain this object or this method or this method's implementation, as it's a simple function call.

提交回复
热议问题