Is this a retain cycle? - ios

I usually get a warning when I call anything on self in a block retained by self:
[self.someView doSomething:^{
self.aVar = #"Hello!";
}];
I have to do:
__weak SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
}];
But if I call a method on weakSelf, and that method uses self, will that lead to a retain cycle even though I don't get a warning? I am talking about this:
__weak SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
[weakSelf aMethod];
}];
and aMethod uses self

As long as your weakSelf is declared outside your block, there is no retain cycle.
Use of objects inside the block implicitly increments the retain count. But you'd be calling aMethod on weakSelf rather than self, so the retain count is not affected.

You should declare the __weak to self outside of your block:
__weak SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
[weakSelf aMethod];
}];
Else the compiler would have already retained self since it is used with the block.
Beter even is using the __block directive, because __weak is iOS 5 and higher only.
__block SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
[weakSelf aMethod];
}];
About an other method calling self and causing retain, I've never seen this behavior. I always use the __block directive which might catch that one as well.

Related

Should I use weakSelf in nested blocks?

I'm trying to correctly avoid retain cycles with blocks in Objective C, and am not sure about having nested blocks.
If I write a simple block like this:
[self doSomethingWithBlock:^{
[self doSomethingElse];
}];
The compiler catches and warns me that this could cause retain cycles. I change it as follows to avoid the cycle:
__weak __typeof(self)weakSelf = self;
[self doSomethingWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSomethingElse];
}];
When I write something like this:
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
[self doYetAnotherThing];
}];
}];
The compiler is happy, but I'm not convinced that it's safe. Even though there is an intermediary object in between, it still looks conceptually the same as above, but now it's a cycle with 3 retains.
Should it be like this instead?
[self doSomethingWithBlock:^(MyObject* object){
__weak __typeof(self)weakSelf = self;
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doYetAnotherThing];
}];
}];
Or like this?
__weak __typeof(self)weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doYetAnotherThing];
}];
}];
In this situation, you are not worried about cyclic references. What you are worried about is a situation where the object self isn't actually needed anymore, but using self inside a nested block would keep it unnecessarily alive. For example, if you have a view controller that should go away when the view is removed by the screen, but you download an image that you would like to display in the controllers view. If the image arrives long after the view is already gone, you don't want the view controller alive anymore.
Best is
__weak typeof (self) weakSelf = self;
before calling the outermost method. Then within every block that ought to use self, you add
typeof (self) strongSelf = weakSelf;
and use strongSelf within that block. Depending on the situation, you might want to check that strongSelf isn't nil at that point, but sending messages to strongSelf when it is nil has no effect, so if all you do is sending messages and getting or setting properties, then a check for nil is not necessary.
What happens if you don't do this? The difference will be that self may be kept alive unnecessarily into the innermost block, if you use self everywhere (or just in the innermost block).
You should not capture something weakly just because you get a warning from the compiler; the compiler warning is just guessing; it doesn't know how the methods you call make the references. You should only do this if you understand the architecture of the references and determine that there is a cycle and determine that capturing a weak reference instead still preserves the intended behavior. You haven't shown us the code of -doSomethingWithBlock:. It would only create a retain cycle if inside that method it assigns the block to a property or instance variable of self. Does it do that or not? If not, then there is no retain cycle, and there is no point to the outer block capturing self weakly.
Assuming that the outer block capturing self weakly is right, the examples where the outer block captures self strongly are out of the question. The remaining questions would be whether the inner block should capture self (or whatever version of self, e.g. strongSelf, is appropriate) strongly. In other words, whether you would do something like this:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
[strongSelf doYetAnotherThing];
}];
}
}];
or something like this:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doYetAnotherThing];
}
}];
}
}];
Again, the main issue to determine is whether there is a retain cycle if the inner block captures self strongly. There would only be a retain cycle if [object doSomethingElseWithBlock:... somehow assigns the block to a property or instance variable of self. But how could it? The method is called on object, not self. The method does not get self in any way. Unless there is something complicated going on, the method is not going to assign to a property or instance variable of self, so it is unlikely to create a retain cycle. This means that the inner block capturing self weakly is not necessary to prevent a retain cycle.
But whether the inner block captures self weakly or strongly could affect the behavior. Namely, if the inner block captures self weakly, self could be deallocated by the time the block is run, in which case [strongSelf doYetAnotherThing]; will not be executed, whereas if the inner block captured self strongly, it would keep self alive and [strongSelf doYetAnotherThing]; would be executed. So it depends on what -doYetAnotherThing does. If it performs some UI operation on self which is a UI view or something, then whether you perform it on a view that is no longer displayed doesn't make a difference. But if it for example sends something to the network or something, then whether or not it is executed can make a big difference.
Xcode 8 beta 4 underlines the self keyword, and warns of a possible retain cycle for having used it inside the block.
Per Apple Developer Connection's Programming in Objective-C (Working with Blocks):
Avoid Strong Reference Cycles when Capturing self If you need to
capture self in a block, such as when defining a callback block, it’s
important to consider the memory management implications.
Blocks maintain strong references to any captured objects, including
self, which means that it’s easy to end up with a strong reference
cycle if, for example, an object maintains a copy property for a block
that captures self:
#interface XYZBlockKeeper : NSObject
#property (copy) void (^block)(void);
#end
#implementation XYZBlockKeeper
- (void)configureBlock {
self.block = ^{
[self doSomething]; // capturing a strong reference to self
// creates a strong reference cycle
};
}
...
#end
The compiler will warn you for a simple example like this, but a more
complex example might involve multiple strong references between
objects to create the cycle, making it more difficult to diagnose.
To avoid this problem, it’s best practice to capture a weak reference
to self, like this:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
By capturing the weak pointer to self, the block won’t maintain a
strong relationship back to the XYZBlockKeeper object. If that object
is deallocated before the block is called, the weakSelf pointer will
simply be set to nil.
This site reportedly provides a means for making the self keyword weak whenever it's used inside a block; it also provides instructions for returning a weak self or class object formerly strong, strong again:
https://coderwall.com/p/vaj4tg/making-all-self-references-in-blocks-weak-by-default
Look at the answer for this question.
I'd do this
__weak typeof (self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
[weakSelf doYetAnotherThing];
}];
}];

Two ways of block for preventing retain-cycle

I usually use block like this if there might be a retain-cycle:
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
}];
}
But recently I saw another way like:
- (void)someFunctionWithParam:(id)param {
__weak __typeof(param) weakParam = param;
[self setHandler:^{
__typeof(weakParam) strongParam = weakParam;
[strongParam doSomething];
}];
}
What's the difference between them?
Edit1: Does it mean the param won't be release when self running the handler?
In the second example, there is no benefit to creating the strongSelf variable in that specific case, but I can show you an example where there is a benefit.
In the first example, the statement [weakSelf doSomething] loads the reference in weakSelf, retains it, sends the doSomething message, and then (after doSomething returns) releases the reference. The second example does essentially exactly the same steps “by hand”.
Here's a slightly different example:
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
[weakSelf doAnotherThing];
}];
}
In my code, suppose there's only one strong reference to the self object at the time the block is called. The [weakSelf doSomething] statement creates a second, temporary strong reference to it. While doSomething is running, another thread releases the other strong reference. When doSomething returns, the statement releases its temporary strong reference. Now self has no more strong references, so it is deallocated and weakSelf is set to nil.
Then the [weakSelf doAnotherThing] statement runs. It wants to load and retain the contents of weakSelf, but because weakSelf is now nil, the statement just uses nil. It sends the doAnotherThing message to nil, which is allowed and doesn't crash. It just does nothing. It doesn't call the method.
This might not be behavior you want. Maybe you always want doAnotherThing to run on self if doSomething ran. That's when you need the pattern in your second example:
- (void)someFunctionWithParam:(id)param {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
__typeof(weakSelf) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doAnotherThing];
}];
}
Here, when the block is called, it immediately stores a strong reference to self in strongSelf (or it stores nil if weakSelf has already been set to nil). The strongSelf reference can't be released until after the last use of the strongSelf variable, so it's impossible for self to be deallocated after doSomething but before doAnotherThing.

Weak Self in Blocks

Do I need to check if weak self is nil in blocks?
I create weakSelf pointer like:
__weak typeof(self) weakSelf = self;
and in the beginning of the blocks I do
if(!weakSelf){return;}
is this unnecessary? or does it depend on whether I coded the rest correctly so that when the self dies, others die too?
That check is unnecessary, and is giving you a false sense of security.
Here's the problem:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (!weakSelf) { return; }
// THE LINE OF INTEREST
[weakSelf doSomething];
});
At THE LINE OF INTEREST, some other thread might clear the last strong reference to self, at which point weakSelf is set to nil. So the doSomething message gets sent to nil, which is “safe” (it does nothing), but might not be what you expected!
It's worse if you want to take a different action when weakSelf is nil, e.g.
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf) {
[weakSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
In this case, between the time the block verifies that weakSelf is not nil and the time it sends the doSomething message, weakSelf might become nil, and neither doSomething nor doSomethingElse will actually run.
The correct solution is this:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
In this case, copying weakSelf to strongSelf (which is strong by default) is atomic. If weakSelf was nil, strongSelf will be nil. If weakSelf was not nil, strongSelf will not be nil, and will be a strong reference to the object, preventing it from being deallocated before the doSomething message.
It seems quite unnecessary since calling a message on nil is a no-op. (Nothing happens)
^{
[weakSelf doSomething]; //Does nothing if weakSelf is nil
}
The only reason I can think you might want to do this is if other messages (not on self) shouldn't be called
^{
// Here I don't want to add weakSelf as an observer if it's nil
if (!weakSelf) return;
[OtherClass addObserverForSomething:weakSelf];
}
Weak references do not retain the referred object. If none else is retaining it, the object is released and the weak references refers to nil.
Therefore it is possible that your code is executed with a weakSelf that refers nil. But this is no reason to check for it at all. Especially in Objective-C you use a defined behavior, if you send a message nil. I. e. it is perfect code, if you set a property using a nil reference. It simply goes to nowhere.
Of course sometime you do not want to interact with nil. In such a case you have to check for it.
BTW: You need weakSelf only in some, rarely circumstances. It is an urban legend that in closures in general references to self has to be weak to prevent retain cycles. It has not been true, it is not true and it will never be true.

What is the reason of #strongify

In ReactiveCocoa there is macro to prevent retain cycle #weakify and #strongify. From my understanding #weakify do something like what I usually do that is create __weak reference for using in the block, but what about #strongify?
Why do I need to make it strong again in the block?
Here is some sample usage:
#weakify(self);
[RACObserve(self, username) subscribeNext:^(NSString *username) {
#strongify(self);
[self validateUsername];
}];
If you just use a weak reference within the block, self can get deallocated while the block is being executed. But if you want to ensure that self stays in memory until the block finishes execution, you have to convert the weak reference back to strong.
The #weakify(self) and #strongify(self) are equivalent to
__weak typeof(self) __weak_self__ = self; // weakify
[self setBlock:^{
__strong typeof(__weak_self__) self = __weak_self__; // strongify
[self doSomething];
}];
You must use __weak_self__ if there's no #strongify(self) in the block.
So, the most important reason is that you can still use self instead of __weak_self__ in the block. To avoid mistakes like this, copying [self doSomething]; into the block, but forget to change self to __weak_self__. It happens more than "self can get deallocated while the block is being executed".

weakSelf on queue calling method that use self inside

Is it ok if i do something like:
-(void)example{
__weak __typeof__(self) weakSelf = self;
dispatch_queue_t dispatchQueue = dispatch_queue_create("q_getRestaurants", NULL);
dispatch_async(dispatchQueue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf doSomething];
});
});
}
-(void)doSomething{
//can i use self inside this method????
self.view.backgroundColor = [UIColor redColor];
}
The thing is that i wanna know if there is ok if i use self inside the do something method that is being called from a queue that has a weakSelf call.
Yes. You're good there. Only variables inside the block itself are retained.

Resources