Clarification on Apple's Block Docs?

前端 未结 2 1926
挽巷
挽巷 2021-01-07 00:51

I am working through some retain-cycle issues with blocks/ARC, and I am trying to get my head around the nuances. Any guidance is appreciated.

Apple\'s documentation

2条回答
  •  孤独总比滥情好
    2021-01-07 01:31

    Think of the case of using instanceVariable as an equivalent of writing self->instanceVariable. An instance variable is by definition "attached" to the self object and exists while the self object exists.

    Using instanceVariable (or self->instanceVariable) means that you start from the address of self, and ask for an instance variable (that is offset of some bytes from the self object original address).

    Using localVariable is a variable on its own, that does not rely on self and is not an address that is relative to another object.

    As the blocks capture the variables when they are created, you typically prefer using instance variables when you mean "when the block is executed, I want to get the value of the instance variable at the time of the execution" as you will ask the self object for the value of the instance variable at that time (exactly the same way as you would call [self someIVarAccessorMethod]). But then be careful not to create some retain cycles.

    On the other hand, if you use localVariable, the local variable (and not self) will be captured when the block is created, so even if the local variable changes after the block creation, the old value will be used inside the block.

    // Imagine instanceVariable being an ivar of type NSString
    // And property being a @property of type NSString too
    instanceVariable = @"ivar-before";
    self.property = @"prop-before";
    NSString* localVariable = @"locvar-before";
    
    // When creating the block, self will be retained both because the block uses instanceVariable and self.property
    // And localVariable will be retained too as it is used directly
    dispatch_block_t block = ^{
      NSLog(@"instance variable = %@", instanceVariable);
      NSLog(@"property = %@", self.property);
      NSLog(@"local variable = %@", localVariable);
    };
    
    // Modify some values after the block creation but before execution
    instanceVariable = @"ivar-after";
    self.property = @"prop-after";
    localVariable = @"locvar-after";
    
    // Execute the block
    block();
    

    In that example the output will show that instanceVariable and self.property are accessed thru the self object, so self was retained but the value of instanceVariable and self.property are queried in the code of the block and they will return their value at the time of execution, respectively "ivar-after" and "prop-after". On the other hand, localVariable was retained at the time the block was created and its value was const-copied at that time, so the last NSLog will show "locvar-before".

    self is retained when you use instance variables or properties or call methods on self itself in the code of the block. Local variables are retained when you use them directly in the code of the block.

    Note: I suggest you watch the WWDC'11 and WWDC'12 videos that talks about the subject, they are really instructive.

提交回复
热议问题