问题
When using a __weak
self
reference in my block that runs on a background thread, do I only need to check for nil
in the beginning, or can the __weak
self
become nil even during execution after the first nil
test has passed? I want to access some ivars from self
in the block and I need the latest values at the time the block is executing.
回答1:
If no one is holding a reference to self
then yes. You can mitigate this by taking a strong reference in the block
__weak __typeof(self) weakSelf = self;
^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
};
回答2:
You can avoid having your reference set to nil by strongly referencing it from inside the block.
Get a strong reference to your weak pointer inside the block.
__weak MyObject *weakSelf = self; // a weak reference
myBlock = ^{
MyObject *innerSelf = weakSelf; // a block-local strong reference
NSLog(@"MyObject: %@", innerSelf);
};
Avoid using the variables directly, because it will cause retain cycles. If you use an instance variable directly within a block, the block will capture self so you'll have to reference the instance variables using their accessors.
__weak MyObject *weakSelf = self;
myBlock = ^{
MyObject *innerSelf = weakSelf; // a block-local strong reference
NSLog(@"MyObject: %@", innerSelf);
NSLog(@"MyObject ID: %d", innerSelf.objectID);
};
If you use the instance variables directly like this:
NSLog(@"MyObject ID: %d", _objectID);
The compiler interprets _objectID
as self->_objectID
, where self is captured by your block.
回答3:
It is in the nature of a weak reference that it can become nil at any time, when the last strong reference is removed in another thread. This is fatal if you access member variables because you will crash, and it is fatal if you call a method on that weak variable, since self is unsafe unretained.
There is a trivial way to fix this which everyone uses: Store the weak variable into a string one before doing anything, without any checks. Then you check whether the strong variable is nil; that check is needed once.
Turn all warnings on in Xcode, so you will get a warning if you do anything dangerous.
来源:https://stackoverflow.com/questions/29343394/can-weak-self-turn-nil-in-the-middle-of-the-block