Accessing BOOL within blocks - ios

I am trying to set a flag using a BOOL within a block.
I declare the BOOL like this:
#property(nonatomic) BOOL flag;
And within the block:
__strong typeof(self) strongSelf = weakSelf;
if(strongSelf->_flag)
My question is, if I do:
__weak typeof(self) weakSelf = self;
if(weakSelf->_flag)
I would get an error:
"dereferencing a __weak pointer is not allowed die to possible null
value caused by a race condition, assign it to strong variable first"
Can someone explain to me what this means?
In addition, it seems funny to me I have to reference the BOOL using __strong
(i.e. strongSelf->_flag), would that be the same as using self->_flag, because I would be using a strong self here?
More over, if I declare the BOOL as an ivar instead of a property:
BOOL flag;
It would give me a warning also when I use it within the block:
if(flag)
And so I would need to do the following as well:
__strong typeof(self) strongSelf = weakSelf;
if(strongSelf->flag)
This baffles me, because normally we reference an ivar without self, just flag, but the above case seems to me that it is accessing the ivar like self->_flag.
??
I could have use something else such as a NSNumber and good riddance to all this, but my curiosity urges me not to turn a blind eye on it.

I assume you scheduling the block operation in some operation queue or so when the block executes later in the future.
You should not assign self to weakSelf inside the block. You should do this outside the block
__weak typeof(self) weakSelf = self;
if(weakSelf->_flag)
__weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.
Apple arc docs.
You actually want your weakSelf be not null to do some stuff with it. To do so you must declare assign it to a variable with strong ownership qualifier.
Sketch:
__weak id weakSelf = self;
schedule_block(^{
// at this point the object pointed by weakSelf may or may not be deallocated
id strongSelf = self; // after this point the object referenced by `strongSelf` will not be deallocated at least `strongSelf` to the end of current block
//You may safely work with `strongSelf` and be sure the object will live at least to the end of current block
});
To sum up: to be sure the object will not be deallocated while you work with it you should obtain a strong reference to it. On the other hand to prevent memory leaks you should use weak references. The algorithm looks like this:
obtain weak reference to object of interest
schedule block
at the start of block obtain a strong reference
if object still live - do whatever you need
if object was deallocated earlier - skip operations in block
iVar is just a member of C-structure the compiler creates for the class at compile time. All references to ivars will be compiled to self-><ivar_name>.
You may refer to Apple's docs for details or to LLVM specs on ARC or LLVM specs on blocks

You start with a weak pointer to an object. The object can disappear at any time, setting the weak pointer to nil. Once you assign it to a strong pointer, the strong pointer may have been set to nil if the weak pointer was nil at the time, but once it is set to non-nil, it stays non-nil because it holds a reference keeping the object alive.
if (strongSelf->_flag)
is dangerous, because strongSelf could be nil, leading to a crash.
if (strongSelf != nil && strongSelf->_flag)
is safe because the flag will not be tested unless strongSelf is not nil.
if (weakSelf->_flag)
is obviously also dangerous. But perhaps surprising is that
if (weakSelf != nil && weakSelf->_flag)
is also dangerous, because just because weakSelf was not nil when you checked it, doesn't mean it's not nil a nanosecond later when you try to access _flag.

Related

Do I need to check for nil on my strongSelf = weakSelf assignment inside a block?

For example, I'm using SVInfiniteScrolling (https://github.com/alexanderedge/SVInfiniteScrolling).
I have some code that looks like this...
- (void)initializeInfiniteScrollingForTableView {
__weak MyViewController *weakSelf = self;
[self.tableView addInfiniteScrollingWithActionHandler:^{
MyViewController *strongSelf = weakSelf;
if (!strongSelf.endReached) {
[strongSelf fetchData];
}
else {
[strongSelf.tableView.infiniteScrollingView stopAnimating];
}
}];
}
What I'm wondering is... do I need to check strongSelf for nil before using like this...
...
[self.tableView addInfiniteScrollingWithActionHandler:^{
MyViewController *strongSelf = weakSelf;
if (strongSelf) { // <== ** Is this needed? **
if (!strongSelf.endReached) {
Here is why I ask. From point #3 on this link (http://www.apeth.com/iOSBook/ch12.html#EXstrongWeakDance) it says "The nil test is because, in a multithreaded situation, our weak reference to self may have vanished out from under us before the previous step; it would then be nil, because it’s an ARC weak reference, and in that case there would be no point continuing."
Is this check needed? I thought the first time you used the reference to weakSelf within the block, it is retained for the duration of the expression?
For the code you posted, checking for nil is unnecessary.
This line of code:
if (!strongSelf.endReached) {
Will eval to false if strongSelf is nil. Further reading: Sending a message to nil?
And then this line of code will execute:
[strongSelf.tableView.infiniteScrollingView stopAnimating];
That line will just do nothing at all (not even an error) if strongSelf is nil.
However, some developers consider it a best practice to check for nil anyway, incase somebody later adds the code and it does care about nil. So you should consider doing:
MyViewController *strongSelf = weakSelf;
if (!strongSelf) {
return;
}
... the rest of your code ...
I think in your line:
if (!strongSelf.endReached) {
this will evaluate to YES if self is nil, which is not probably not you intend.
It happens that your code does the correct thing (do nothing) because both clauses only use self to call methods and then nothing will happen. The end result is the same as if you had the nil-check but the execution path is wrong. This might have consequences in the future if someone adds code that doesn't use self.
Your source is referring to the fact that weakSelf may have been deallocated and nil'd before execution of the block could even begin; and therefore, before strongSelf acquired a strong reference and retained it. The strongSelf is to ensure that the object referenced by weakSelf is not nil'd during the block's execution.
There is no notion in ARC of "using" a variable making it necessary to retain it when dealing with __weak variables -- __weak is explicitly opting out of this.
With that said, the check isn't strictly speaking necessary in this case, since messages to nil are always no-ops. If you intended to insert strongSelf into an array, or if it being deallocated between messages would put your program into an invalid state, it would be another matter.
To conclude, whenever you need to guarentee that a __weak variable will not be nil'd for a period of time, use __strong, and check before using it that it is not nil.

Can __weak self turn nil in the middle of the block?

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.
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;
}
};
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.
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.

Strong reference to a weak references inside blocks

Why is it necessary to have a strong reference to a weak reference inside a block?
I understand that having a weak reference inside the block will avoid retain cycles. But why must there be a strong reference to the weak one again?
Background:
As described by Mason this is best practice.
I know the proper way to refer to self inside a block is to create a weak reference outside the block, and then a strong reference to that weak reference inside the block[...]
Example:
__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
typeof(self) strongSelf = weakSelf;
// code using strongSelf
});
Imagine that the last remaining strong reference to self is held on a different thread to the one that your block runs on.
Now this happens:
__weak typeof(self) weakSelf = self;
void (^someBlock)(id) = ^(id data){
if (weakSelf != nil) {
// last remaining strong reference released by another thread.
// weakSelf is now set to nil.
[myArray addObject:weakSelf];
}
});
This will crash with an NSInvalidArgument exception for adding nil to an array.
Making the reference strong before use removes the potential race condition and ensures that the pointer will always point to the same object.
If you are 100% certain that an object will only ever be referenced by one thread, it isn't strictly necessary to do this. But it's bad practice to make that assumption.
It's not inherently necessary, but the general idea is to make sure that the object pointed to by weakSelf is not dealloc'ed while the block is executing. Creating the strong reference has the side effect of retaining the object. That retain will be released by ARC when the strong reference goes out of scope. It's largely defensive. Generally speaking, you should aim to provide other (better) guarantees that your system remains stable during block execution.

ARC, self and blocks

I thought I understood the usage of self in a block that is copied is a no no.
But in an attempt to clean my code i enabled a bunch of warnings in Xcode, one called "Sending messages to weak pointers"
so now in all my blocks, every time I use my created weakself reference __weak typeof(self) weakself = self;
I get this warning: Weak receiver may be unpredictably set to nil
a trivial example:
__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{
[weakself doSomething]; //warning.
}];
I have seen answers which define a version of self within the block like so:
__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{
typeof(self) selfref = weakself;
[selfref doSomething]; //no warning.
}];
So I'm wondering what actually happens here:
Am I just tricking the compiler?
what does a strong reference to a weak reference do?
anything else I'm missing.
Thanks.
I thought I understood the usage of self in a block is a no no.
This is not strictly correct. Blocks retain the objects in them, so don't use self in a block if your block is retained by self.
For example, you can use self just fine in a UIView animation block. This is because your view controller (or whatever code is calling the animation) doesn't have a pointer to the UIView animation block.)
Am I just tricking the compiler?
No.
What does a strong reference to a weak reference do?
If the weak reference is not nil, the retain count of the receiver is increased. This will stop the object from being deallocated while you're using it.
Remember, ARC will deallocate objects when there are no longer strong references to them. By creating a strong reference inside the block, you're preventing possible deallocation until you're done with it.
anything else I'm missing.
I recommend reading the Practical Memory Management section of the Advanced Memory Management Programming Guide. Especially, read the subsection "Use Weak References to Avoid Retain Cycles".
Remember that in ARC, an object will not be deallocated as long as there's a strong reference to it.
When an object has a weak reference, the object might be deallocated (if there's no other strong reference to the same object), so a weak reference doesn't ensure the objects life.
By doing this:
typeof(self) selfref = weakself;
you're ensuring that you have a strong reference to that object before you use it (selfref is the strong reference pointing to the same object weakself is referring to). If you don't do this, the object could be deallocated while you use it.
Strong reference to a weak reference retains an object. It could be important in following case
__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{
[weakself allocateSomething]; // (1)
// ..... code (2)
[weakself freeSomething]; // (3)
}];
If Weak receiver will be unpredictably set to nil in line (2) resources could be successfully allocated in (1) but not freed in (3). To avoid such problems strong reference could be used.
[aClass doSomethingInABlock:^{
typeof(self) selfref = weakself;
[selfref allocateSomething]; // (1)
// ..... code (2)
[selfref freeSomething]; // (3)
}];
Now if selfref is not nil in (1) it will also be valid in (2) and (3).

weak reference cause crash bug

I have seen the following code in WWDC 2011- Session 322 Objective-C Advancement in Depth
-(void) startBlinker{
__weak MyClass * weakSelf = self;
blinker = [BlinkerService register:^{
MyClass *strongSelf = weakSelf;
if(strongSelf){
[strongSelf->myView blink];
}
}];
}
I think I can implement it just check weakSelf like
if(weakSelf){
[weakSelf->myView blink];
}
why the code use a strongSelf?
If the object a weak reference points to is deallocated, the weak reference evaluates to nil. Calling methods on nil is okay but accessing fields using the arrow operator is not. So you have to make sure the pointer is not nil before accessing the field via the arrow pointer.
if(weakSelf){ // no weak sheeps this week
// weakSelf may get deallocated at this point.
// In that case the next line will crash the app.
[weakSelf->myView blink];
}
The strong self guarantees that self will not be deallocated between the if and the statements in the if block.
Usually a weak reference is done like this to avoid retain cycles in blocks. Blocks retain self which causes a retain cycle if you try to access a strong reference to self. So you create a weak self outside the block and access it within the block to avoid the retain cycle.
Ahmed Mohammed is correct, however another possible solution is to declare myView as a property, rather than as an iVar and do this:
-(void) startBlinker{
__weak MyClass * weakSelf = self;
blinker = [BlinkerService register:^{
MyClass *strongSelf = weakSelf;
[strongSelf.myView blink];
}];
}
This way, you don't really care if strongSelf is nil or not.

Resources