Objective-C - Blocks and memory management? - objective-c

__weak MyClass *selfReference = self;
dispatch_async(dispatch_get_main_queue(), ^{
[selfReference performSomeAction];
});
When do you need to pass a weak reference to a block?
Does this rule apply to dispatch_async as well as custom blocks?
Does a block copy the iVars used in it or does it retain them?
Who owns the variables initialized inside a block? Who should release them?

1, 2) Blocks retain the object-pointers in it (any blocks, dispatch_async blocks are nothing special). This usually isn't a problem, but can lead to retain-cycles, because the block can be associated with an owner object and that owner object (often self) might be retained by the block. In that case you should use a weak variable and then reassign it to a strong capture:
__weak MyClass *weakSelf = self;
self.block = ^{
MyClass *strongSelf = weakSelf;
...
[strongSelf ...];
[strongSelf.property ...];
[strongSelf->iVar ...];
}
Note: If you access an iVar directly, the compiler will transform that into self->iVar and thus retains self!
3) Blocks only retain the pointers, they don't copy them.
4) Variables created inside a block belong to that block and will be released when that block goes out of scope.

Related

Using an ivar inside a method which is called from a block

I want to use an ivar in a method that is being called from a block. Is it fine to call the ivar directly from it without causing a retain cycle?
I have seen other questions related to calling properties- saying that we 'can' use self. Just wanted to make sure about ivars, can we call ivar directly or do we need to use self->_myInstanceVariable explicitly?
__weak MyClassName *weakSelf = self;
[MyBlockCreator myBlock:^{
MyClassName *strongSelf = weakSelf;
[strongSelf doSomething];
}];
- (void) doSomething {
_myInstanceVariable = someObject
// is it fine to use the ivar directly above?
// or do we want use self explicitly?
// like self->_myInstanceVariable
}
In this case you don't need to make the reference weak/strong at all, the only situation in which you can cause a retain cycle is if self references a block and a strong version of self is captured within that block. Since self doesn't retain the block in question, there would be no retain cycle even using a strong reference.
[Foo doWithBlock:^{
bar.baz = #"Hello World"; // Totally fine without weak/strong since bar doesn't retain the block here.
}];
In situations where self holds a strong reference to a block and the block refers to self, you need to make the reference weak outside the block then make it strong again inside.
__weak id weakSelf = self;
[self doWithBlock:^{
id strongSelf = weakSelf;
strongSelf.baz = #"Ok";
}];

Does assigning a weak pointer to a strong pointer copy the object?

The common pattern to avoid capturing self within a Block is to create a weak self outside the Block and use this to create a "locally strong" version of self within the Block (inner self).
__weak ClassX *weakSelf = self;
[someOtherObject methodThatTakesCOmpletionBlock: ^{
ClassX innserSelf = weakSelf; //innserSelf creation?
[someObject send:innerSelf.prop;}];
What happens when the innserSelf creation line is executed? Is innerSelf a copy of self at the time the method methodThatTakesCompletionBlock: is sent to someOtherObject?
This question just focusses on what happens when the innserSelf line is executed. I've seen Strong reference to a weak references inside blocks which is related but doesn't address this point.
Consider:
__weak id weakSelf = self;
[other doSomething: ^{
__strong id strongSelf = weakSelf;
....
}];
When other copies the block, there is no strong reference.
When other executes the block, then the strong reference is created at the beginning of the block's execution. When the block is done, the execution scope is gone and, thus, the strongSelf reference is destroyed.
Whether other hangs onto the block or not is irrelevant; the strongSelf reference only exists during block execution.
Assigning a weak pointer to a strong one does not copy the object. Both pointers will point to the same object. The strong pointer retains thus adding +1 to the retain count. The weak pointer does not alter the retain count

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.

Do methods called from within a block need to use weakSelf?

If the code inside a block calls a method, will a retain cycle exist if that method references self? In other words, does all code downstream of a block need to use the weakSelf/strongSelf pattern?
For example:
__weak __typeof__(self) weakSelf = self;
Myblock block = ^{
[weakSelf doSomething];
};
. . .
- (void)doSomething
{
self.myProperty = 5; // Is this ok or does it need to use a weakSelf?
}
Objective-C is not scoped like you suggest, namely, you don't have access to weakSelf from within -doSomething. Furthermore, as you are calling -doSomething on weakSelf, "self" within that call is actually referring to the same object that weakSelf is.
In short, no, you shouldn't, you can't and you shouldn't.
Retain cycle will be triggered only if you retain self inside the block. Otherwise it will just throw a warning only.
This is fine you can use this. Because block retains every vars used inside, so retain cycle would be like
Self would retain block
If block retains self then
Self would again retain block
block would retain self, so cycle goes on
The thing you are doing in method is just message passing. Everytime block is called a message would be sent to self to doSomething. And you can retain self in doSomething method it wont trigger retain cycle because this method dont have cycle loop to self. Hope you understand :)
- (void)doSomething
{
self.myProperty = 5; // Is this ok or does it need to use a weakSelf?
}
you can do this to get rid of retain cycle problem.
[self class] __weak *weakSelf = self;
self.completionBlock = ^{
[self class] __strong *strongSelf = weakSelf
[weakSelf doSomething];
};

Why do I need to create a threadsafe version of self for some completion blocks and not others?

I have a view with a UIPageViewController and on the method to set view controllers I have use a thread safe instance of self like this:
__block typeof(self) threadedSelf = self;
[self.pageController setViewControllers:#[p]
direction:UIPageViewControllerNavigationDirectionReverse
animated:YES
completion:^(BOOL finished){
if (finished) {
[threadedSelf performSelectorOnMainThread:#selector(setNavTitleText) withObject:nil waitUntilDone:NO];
}
}];
The completion block looks similar to other completion blocks, like the UIView animation method, but this is the first completion block where I've had to create a block version of self. Why is this method different than other completion callbacks? Is it because this is an instance method where the UIView animation is a class (static) method?
This isn't really a thread safety issue, it's a retain cycle issue. Blocks retain the objects they use. Evidently, from the warning, this block is being retained by self, so if it also uses/retains self then you have a retain cycle.
You should use the __weak qualifier on the pointer to self that you use in the block, like:
__weak typeof(self) weakSelf = self;
Both __weak and __block are frequently used for variables that will appear in blocks, but they have different purposes. The __weak qualifier prevents the block from retaining the object and is exactly the tool you need to prevent a retain cycle. The __block qualifier does prevent the block from retaining the object, but its purpose is really to indicate that the object might be changed inside the block (i.e. changes made to the object inside the block must be visible outside of the block). That is not the case in your example. You refer to self but you are not modifying the pointer (self = foo). Therefore you should use the __weak qualifier instead of the __block qualifier.
In many cases you need neither qualifier. There will be a retain cycle only if the block is actually retained by an object referred to inside the block. Frequently, you will use blocks that are not retained by any object you own, for example:
[UIView animateWithDuration:0.2 animations:^{
[self makeSomeChangesToBeAnimated];
}];
Here the animation block can safely refer to self with no qualifier, because the block is not retained by self. It might be retained by something else but not by self, so you do not need to use the __weak qualifier.
If self retains a block that refers to self, we have a retain cycle. The warning you are trying to avoid is telling you that that might happen here. I don't know whether it's true or not but, given the explicit warning, I take no chances: I pass a weak version of self into the block, using the "weak-strong dance".