3

I have a basic understanding of weak reference with the blocks. The problem I am facing is,

Whenever I access self inside the block, the retain count of self gets increased by 2, where as when I access self inside the default block(example UIViewAnimation) the retain count for self gets increased by 1.

Just wanted to understand why it is getting increased by 2. enter image description here

Thanks in advance!

aToz
  • 2,463
  • 1
  • 24
  • 34
  • The block will want to retain 'captured' iVars (like self) to ensure the reference remains valid ... ie that `self` does not deallocate before it executes. You will find good info on this here (different treatment for MRC and ARC. http://stackoverflow.com/questions/19227982/using-block-and-weak – YvesLeBorg Jan 02 '15 at 13:55
  • 1
    Also to better understand weak read https://dhoerl.wordpress.com/2013/04/23/i-finally-figured-out-weakself-and-strongself/ – David H Jan 02 '15 at 13:59
  • 5
    http://whentouseretaincount.com – jrturton Jan 02 '15 at 14:25
  • @YvesLeBorg thanks for sharing the link. I was just checking the behavior of the block for that specific case, where it goes to 2. – aToz Jan 02 '15 at 14:36
  • @David thanks for sharing the links. I was just checking the behavior of the block for that specific case, where it goes to 2. – aToz Jan 02 '15 at 14:36
  • @jrturton the link you have shared made me think over the retain count. – aToz Jan 02 '15 at 14:37
  • 4
    When ARC is running, looking at retain counts is absolutely pointless. It will do nothing more than confuse you. There are very few conclusions that you can draw from any retain counts, and no valid conclusions at all when ARC is involved. – gnasher729 Jan 02 '15 at 16:56
  • @YvesLeBorg: Blocks only "capture" local variables. Never ivars. – newacct Jan 02 '15 at 22:36

2 Answers2

1

According to Clang source code for generating code of Objective-C blocks.

Objective-C blocks literal is generated by EmitBlockLiteral function.

llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) {

LLVM document explains deeply what is Block literal. Anyway this function generates a block descriptor and a copy helper function of the specified block. The copy helper function is for capturing auto variables and self.

buildBlockDescriptor -> buildCopyHelper -> GenerateCopyHelperFunction

In GenerateCopyHelperFunction function, Clang emits objc_storeStrong for each Objective-C object auto variable that will be captured by the block.

for (const auto &CI : blockDecl->captures()) {
    ...
    EmitARCStoreStrongCall(...

So, this line would count up the retain count of self (1 -> 2).

After that, EmitBlockLiteral function emits objc_retain for each Objective-C object auto variable that will be captured by the block, as well.

// Next, captured variables.
for (const auto &CI : blockDecl->captures()) {
    ...
    EmitExprAsInit -> EmitScalarInit -> EmitARCRetain

Therefore this line would count up the retain count of self too (2 -> 3).

I don't know the exact reason. But apparently, there is some reason to retain Objective-C object before capturing object by the block copy helper function.

Kazuki Sakamoto
  • 13,929
  • 2
  • 34
  • 96
-1

Using self inside a block, usually creates a cycle which could be the reason why it gets increased by 2. To fix this, you should try using a weak self. Check this question out

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

Use something like this
__unsafe_unretained typeof(self) weakSelf = self;

Community
  • 1
  • 1
Phil
  • 1,077
  • 1
  • 11
  • 18
  • Using `self` inside a block does not create a cycle. It creates a reference from the block to `self`. It only creates a cycle if you make a cycle -- if you keep a reference from `self` to the block. That is not what is happening here. – newacct Jan 04 '15 at 00:21