playerken

博客园 首页 新随笔 联系 订阅 管理

However, because the reference is weak, the object that self points to could be deallocated while the
block is executing.
You can eliminate this risk by creating a strong local reference to self inside the block:

__weak BNREmployee *weakSelf = self; // a weak reference
myBlock = ^{
BNREmployee *innerSelf = weakSelf; // a block-local strong reference
NSLog(@"Employee: %@", innerSelf);
};

  


By creating the strong innerSelf reference, you have again created a strong reference cycle between
the block and the BNREmployee instance. But because the innerSelf reference is local to the scope of
the block, the strong reference cycle will only exist while the block is executing and will be broken
automatically when the block ends.
This is good programming practice whenever you write a block that must reference self.

 

If you use an instance variable directly within a block, the block will capture self instead of the
instance variable. This is because of a little-known nuance of instance variables. Consider this code
that accesses an instance variable directly:

__weak BNREmployee *weakSelf = self;
myBlock = ^{
BNREmployee *innerSelf = weakSelf; // a block-local strong reference
NSLog(@"Employee: %@", innerSelf);
NSLog(@"Employee ID: %d", _employeeID);
};
The compiler interprets the direct variable access like this:
__weak BNREmployee *weakSelf = self;
myBlock = ^{
BNREmployee *innerSelf = weakSelf; // a block-local strong reference
NSLog(@"Employee: %@", innerSelf);
NSLog(@"Employee ID: %d", self->_employeeID);
};
Does the -> syntax look familiar? It is the syntax for accessing the member of a struct on the heap. At
their deepest darkest cores, objects are actually structs.
Because the compiler reads _employeeID as self->_employeeID, self is unexpectedly captured by the
block. This will cause the same strong reference cycle that you avoided with the use of weakSelf and
innerSelf.
The fix? Don’t access instance variables directly. Use your accessors!
__weak BNREmployee *weakSelf = self;
myBlock = ^{
BNREmployee *innerSelf = weakSelf; // a block-local strong reference
NSLog(@"Employee: %@", innerSelf);
NSLog(@"Employee ID: %d", innerSelf.employeeID);
};
Now there is no direct use of self, so there is no unintentional strong reference cycle. Problem solved.

posted on 2014-11-12 16:48  playerken  阅读(178)  评论(0编辑  收藏  举报