How can a weakly retained block cause a retain cycle when capturing "self" - objective-c

I have a class with a property which is a weak reference to a block.
#interface BlockTest : NSObject
#property (nonatomic, weak) void(^testBlock)();
#end
At another point in the class I use this block like this:
- (void)foobar {
self.testBlock = ^{
[self doSomething];
};
}
The compiler (Apple LLVM 3.0) complains that there might be a retain cycle because self is strongly captured here. But I fail to see how this leads to a retain cycle because the block itself is a __weakreference, so it should be fine. If I understood ARC weak references correctly, when the -foobar method returns the block passed to self.testBlock should be deallocated (if not held elsewhere) and thus also release self.
What's the reason the compiler still thinks there might be a retain cycle?

Blocks strongly capture objects within them regardless of how the block itself is referenced. The retain cycle warning is just that, a warning of the possibility. If you know based on the context of your app that this use will not cause a retain cycle you can safely ignore it. To get rid of the warning, you can pass self through an intermediary, strong or weak, as follows:
__weak typeof(self) weakSelf = self;
self.testBlock = ^{
[weakSelf doSomething];
};
I'd change your block property to be a strong reference and do the above.

Related

In Objective-c blocks, do I need to pass weak/strong self to helpers?

Within blocks, do I need to pass some version of self to helper methods?
In this example, publicMethod() is calling _privateHelper using strongSelf.
But, _privateHelper() is calling _secondPrivateHelper() using self. Is this fine or should I pass down strongSelf to the helpers?
- (void)publicMethod
{
auto __weak weakSelf = self;
dispatch_sync(dispatch_get_main_queue(), ^{
auto __strong strongSelf = weakSelf;
if (!strongSelf) {
return;
}
[strongSelf _privateHelper];
});
}
- (void)_privateHelper
{
[self _secondPrivateHelper]; // <-- what version of `self` is sending the message here? I'm assuming the copied `strongSelf` from above.
}
- (void)_secondPrivateHelper
{
NSLog(#"Hello, World");
}
TLDR
When to use strong or weak depends on how you use the block. In your code strong and weak does not really matter but I will give an example where it matters and explain how to then use weak.
I think you are considering the wrong things here. In your example all pointers to self can (and should) be strong. You do not need to dance the dance here and you should consider using weak only when you create retain cycles which I will discuss in a moment.
In your case note that when you are inside the block you want a strong pointer to self. If you have a weak pointer the block becomes superfluous when self is nil. To get a strong pointer simply change your block to
... ^{
[self _privateHelper];
});
rather than the way you do it. Now (and in your original code) you have (and should have) a strong pointer to self inside both your _privateHelper and _secondPrivateHelper.
But this is not the issue.
Retain cycle
Suppose you have an ivar
#property (strong,nonatomic) void ( ^ block )( void );
Only now do you have potential trouble and you probably need to use weak pointers. The reason being that if somewhere in your code you have
self.block = ^{ [self _privateHelper]; };
the block will retain a strong pointer to self. At the same time, self is keeping, through the ivar, a strong pointer on the block. Can you see the retain cycle? Neither the block nor self will ever be released automatically as both are keeping strong references to the other.
Fixing it
You can change the ivar to weak in which case you break the cycle. If the block goes out of scope the weak ivar goes to nil and there is no retain on self.
You could also do
self.block = ^ { [weakSelf _privateHelper]; };
inside the block to break the cycle. Now if self goes out of scope the block no longer has a hold on it and again there is no retain cycle on self.
Both these fixes are used - a lot of ivars will be weak in a UI environment to prevent the e.g. label keeping a strong reference on the vc while the vc also keeps a strong reference on the label.
When working with blocks you typically use weak pointers to self inside the block only if you potentially have a retain cycle. This is often not an issue and in your code also is not an issue as self does not retain the block. So in general your helper blocks could probably get away with strong pointers to self. You only need to dance the dance if somehow self and the block are creating a retain cycle.
Finally, a third way to fix it is to set the ivar to nil yourself. So you could have code that looks like this
if ( self.block )
{
self.block (); // Execute block
self.block = nil;
}
This also makes sense sometimes e.g. when you want to retain the block and self until the block executes. Here you release the ivar manually by setting it to nil after which it no longer retains self and the cycle is broken albeit manually.
You could even do this inside the block, e.g. change the block to
self.block = ^ { [self _privateHelper]; self.block = nil; /* release when done */ };

Does a reference remain weak if passed as an argument in objective-c?

When I pass self as an argument to a function, does it make any difference if I weakify it first?
For example:
__weak __typeof(self) weakSelf = self;
[self.someObject doWorkWithDelegate: weakSelf];
In the body of the doWork function it assigns it to a strong property
#property (strong) Foo* fooDelegate;
(I know this is terrible, don't get sidetracked).
This will still be a strong reference and cause a memory cycle despite theh fact that I "weakified" the reference first, correct?
Bonus Question: How can I check this myself?
It is the variable weakSelf which is weak. That is, ARC does not emit a retain when a value is assigned to it, nor a release when it goes out of scope (or is assigned a different value).
Since the fooDelegate property is strong, assigning to it releases any old value it may have had and retains the newly-assigned value.
So, yes, that will be a strong reference. It's not clear from what you posted whether it will constitute a retain cycle. The name of the method suggests that the delegate will be cleared (thus released) after the work has been completed. In that case, it's not a problem. It would only be a problem if self.someObject maintained the strong reference until it itself was released and self maintained a strong reference to someObject until self was released.
An important aspect of the original question could be further clarified. "When I pass self as an argument to a function, does it make any difference if I weakify it first?"
Note that in the example code block:
__weak __typeof(self) weakSelf = self;
[self.someObject doWorkWithDelegate: weakSelf];
ARC will perform a retain on each of the objects passed, including the receiver (i.e. self.someObject and weakSelf), and then a release on each when complete, allowing weak objects to be safely used for the lifetime of the called method. So the answer would be no, it doesn't make a difference to make it weak first because it will be strong for the duration of the call.
If the weak variable was simply referenced within a code block callback from the method, then it will still be weak within that scope.
So this is a common pattern to use a weakSelf variable within a block callback to call another method, foo, which then can safely use self because it is no longer weak during that execution of foo. But if self goes away before the callback is executed, then [weakSelf foo] will simply never be called because weakSelf has gone nil.
__weak __typeof(self) weakSelf = self;
[self.someObject doWorkWithCallback:^{
[weakSelf foo];
}];
- (void)foo
{
// Safely use self here.
[self doMoreWork];
}

about __unsafe_unretained or__weak why can resolve retain cycle

//Parent.m
#import "Parent.h"
#implementation Parent{
dispatch_block_t _block;
NSTimer *_timer;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self commonInitialization];
}
return self;
}
-(void)commonInitialization{
__unsafe_unretained typeof(self) weakSelf=self;
//__weak typeof(self) weakSelf=self; the same conculsion
//apple doc:The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to this object until it (the timer) is invalidated.
_timer=[NSTimer timerWithTimeInterval:0.5 target:weakSelf selector:#selector(sayHello) userInfo:nil repeats:YES];// make weakSelf retain count +1
_block=^{
__strong Parent *parent=weakSelf;//also make weakSelf retain count +1,but the actual is that this wont make self retain count +1
[parent sayHello];//
};
// my question is why weakSelf can make _block wont retain self,but _timer will retain self,it look like contradictory
}
-(void)sayHello{
NSLog(#"hello");
}
-(void)dealloc{
NSLog(#"Parent instance can dealloc");
}
#end
In _block I retain weakSelf again like NSTimer will retain target:weakSelf.
My question is why __unsafe_unretained or __weak can make _block unretained self but _timer not. It looks contradictory.
Retain cycles with blocks happen when a class instance has a strong reference to the class and the block, in turn, has a strong reference to that instance. By capturing a weak reference to the instance within the block (weakSelf), that captured reference can be set to nil. Making the reference within the block a strong reference only means that while the block is executing, the instance will not be dealloc'd (because the block still has a live reference).
The timer internally maintains a strong reference to the instance, just as the block does while it's executing. The main difference is that the timer is a long-lived object, and unless you invalidate it or nil all your references to it, the timer still exists, along with its strong reference to your instance.
I really do not know, whether I understood you correctly. Do you mean with "makes retained" "retains"?
However, the difference between the two pieces of code is the time of execution and how references are handled:
Keep in mind that not object references are retained, but the object they points to.
A. Timer
{
__weak typeof(self) weakSelf=self;
_timer=[NSTimer timerWithTimeInterval:0.5 target:weakSelf …];
}
With this code you create an additional local var called weakSelf, that does not retain the object it points to. Moreover, the extent ("lifetime") of weakSelf ends with the C-block (not the closure what you called __block), that means with the closing }. So we have:
{
__weak typeof(self) weakSelf=self;
// does not retain self; no problem
_timer=[NSTimer timerWithTimeInterval:0.5 target:weakSelf …];
// weakSelf dies, since it is weak nothing happens.
}
In such a case it is completly meaningless to weakify self:
{
id anotherSelf=self;
// does retain self: +1;
_timer=[NSTimer timerWithTimeInterval:0.5 target:weakSelf …];
// anotherSelf dies: -1
}
This is always balanced, because ARC care about it. No problem.
So why is there a retain cycle? It is "inside the timer." According to the documentation:
The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to this object until it (the timer) is invalidated.
Therefore, lets go back to your example:
{
__weak typeof(self) weakSelf=self;
// does not retain self;
_timer=[NSTimer timerWithTimeInterval:0.5 target:weakSelf …];
// timer retains the object, weakSelf points to: +1.
// self retains the timer: +1
// result: retain cycle
// weakSelf dies, since it is weak nothing happens.
}
What -timerWithInterval… does, does not depend of the strength of weakSelf. The method does not even see the strength of the reference. It retains an object that the argument points to. Period.
B. Block
Having a block it is different:
{
__weak typeof(self) weakSelf=self;
// does not retain self; no problem
_block=^{
…
};
// weakSelf dies, since it is weak nothing happens.
}
As you can see, there is no problem. Why can be there a retain cycle? This is quite easy: Having a reference inside the block, the referred object is retained when the block is created (similar to timers) and the reference is strong(different to timers):
{
__weak typeof(self) weakSelf=self;
// does not retain self; no problem
_block=^{
… self … // the object self points to is retained, because self is strong. +1
… weakSelf … // the object weakSelf points to is not retained.
…
};
// weakSelf dies, since it is weak nothing happens.
}
This reference lives as long as the block lives. You have to read it correctly: It is like the reference itself has a longer lifetime. Therefore it depends of the strength of the reference.
So there is a big difference, whether you use weakSelf or self (or any other weak or strong reference.)
What is done inside the block …:
_block=^{
__strong id strongSelf=weakSelf;
};
… is meaningless, because this is done, when the block is executed and the local strongSelf will immediately lose its extent. (Again with the closing }.
ARC and block are all compiler work, compiler will add retain release and it will translate block to struct.
NSTimer will hold a strong reference to target, so it will send retain method (it may call objc_retain(id value) in ARC) to weakSelf, self hold timer as a instance variable, retain cycle happens.
Let's take about the block, by default block will retain any NSObject it captures when the block is move from stack to heap.
the _block(in your case) is a instance variable, when it is assigned a block, the block will be send a copy method, so it will move from stack to heap.
But if object it captured is with __weak or __unsafe_unretained attribute, it won't send retain method to it. The rules are defined by compiler, so it works.
If you want to learn the detail, check the source code runtime.c, you may also need to assemble your code because runtime.c doesn't have ARC code.
If you were confused about this line of code __strong Parent *parent=weakSelf , check this answer.

In Objective-C, what does it mean to assign a weak to a strong within a block?

In Objective-C, what does it mean to assign a weak to a strong within a block? What's happening behind the scene?
e.g.
__weak __typeof(self) wself = self;
void (^cmd)() = ^(){
__strong __typeof(self) sself = wself;
if (!sself) return;
...
};
The intent here is two-fold:
First, is the use of:
__weak __typeof(self) wself = self;
This ensures that the cmd block does not maintain a strong reference to self. This ensures that, if cmd was an instance variable of the class, that you don't end up with a strong reference cycle. If you don't use this wself pattern, the class that has cmd as an instance variable would never be released and you'd leak the object that has cmd as an instance variable.
For more information, see the Avoid Strong Reference Cycles when Capturing self section of the Programming with Objective-C: Working With Blocks document.
Second, the use of the following within the block:
__strong __typeof(self) sself = wself;
if (!sself) return;
This ensures that, if the block starts execution, if wself was already deallocated, the block would quit. But if wself has not yet been deallocated, by assigning sself, you're making sure that the object will be retained during the execution of the block.
Also, if you reference any ivars in the block, be aware that you want to dereference them (because otherwise there is an implicit reference to self in the block, potentially leading to that strong reference cycle). But you cannot dereference ivars using a weak pointer (e.g. wself->someIvar is not permitted), but you can with this local strong pointer (e.g. sself->someIvar is ok). Generally you shouldn't be dereferencing ivars anyway, but rather use properties, but nonetheless it's another reason to use a local strong reference to self.
Often, you'll see this construct in conjunction with a class property (or an ivar):
#property (nonatomic, copy) void (^commandBlock)(void);
And, as a matter of convention, you'll generally see more descriptive variable names, weakSelf and strongSelf, thus:
__weak __typeof(self) weakSelf = self;
self.commandBlock = ^(){
__strong __typeof(self) strongSelf = weakSelf;
if (!strongSelf) return;
...
};
This weakSelf/strongSelf pattern is very common when you have your own block properties to your class and you want to (a) prevent strong reference cycles (aka retain cycles); but (b) want to ensure that the object in question cannot be deallocated in the middle of the execution of the block.
If you don't assign weak reference to a strong the object referenced by the weak reference can be deallocated in the middle of the block execution - something you might not expect. if you assign to strong the object is retained for as long as the strong reference is in scope (unless the object has already been deallocated prior to the assignment).
When you assign a weak reference to a strong compiler inserts Objective-C runtime function call into the code that increments the object reference counter as needed to retain it. When the strong variable goes out of scope (or earlier, after the last use of the strong variable) another call inserted by compiler decrements the reference counter.

How is self passed to methods (or how to prevent strong reference cycles)

I'm currently thinking about how to prevent strong reference cycles when using blocks that retain self. The usual way seems to be to just use a weak reference to self:
#property (strong, nonatomic) NSOperationQueue *queue;
- (void)methodA {
__weak id *weakSelf = self;
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
[weakSelf methodB];
}];
[self.queue addOperation:operation];
}
But what if methodB looks like this:
- (void)methodB {
[self someOtherMethod];
}
Would this still cause a strong reference cycle? Or would methodB receive the weak reference to self from methodA as its reference to self? (That is, is methodB's reference to self just a strong reference to the weak reference from methodA?)
Or would methodB receive the weak reference to self from methodA as
its reference to self? (That is, is methodB's reference to self just a
strong reference to the weak reference from methodA?)
A method does not "receive" a strong or weak reference. It receives a reference. "Strong" or "weak" only apply to a variable (usually, an instance variable or variable captured by a block).
weakSelf is a weak reference in the block. Because weakSelf is a zeroing weak reference (__weak), either it points to a valid object, or its value is nil. If the former, it points to a valid object, and methodB is called on it. If the latter, sending a message to nil does nothing, so nothing happens.
You ask if the self in methodB is a strong reference. A strong reference means that it is retained, so if self were a strong reference in methodB, that means it retains self at the beginning of the method and releases it at the end. But why does it matter whether the method retains an argument such as self? Retain cycles refer to objects strongly referencing each other. A function or method will run and then stop; any retains they do on local variables must be temporary by the memory management rules, and have no effect on retain cycles. (The technical answer is no, self is not retained in ARC, and arguments including self are generally never retained in MRC. But as I said this really isn't relevant.)
I finally found a part in the documentation that kind of answers this question. So it really looks like methodB receives the block's weak reference to self.