Always pass weak reference of self into block in ARC?
It helps not to focus on the strong
or weak
part of the discussion. Instead focus on the cycle part.
A retain cycle is a loop that happens when Object A retains Object B, and Object B retains Object A. In that situation, if either object is released:
- Object A won't be deallocated because Object B holds a reference to it.
- But Object B won't ever be deallocated as long as Object A has a reference to it.
- But Object A will never be deallocated because Object B holds a reference to it.
- ad infinitum
Thus, those two objects will just hang around in memory for the life of the program even though they should, if everything were working properly, be deallocated.
So, what we're worried about is retain cycles, and there's nothing about blocks in and of themselves that create these cycles. This isn't a problem, for example:
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
[self doSomethingWithObject:obj];
}];
The block retains self
, but self
doesn't retain the block. If one or the other is released, no cycle is created and everything gets deallocated as it should.
Where you get into trouble is something like:
//In the interface:
@property (strong) void(^myBlock)(id obj, NSUInteger idx, BOOL *stop);
//In the implementation:
[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self doSomethingWithObj:obj];
}];
Now, your object (self
) has an explicit strong
reference to the block. And the block has an implicit strong reference to self
. That's a cycle, and now neither object will be deallocated properly.
Because, in a situation like this, self
by definition already has a strong
reference to the block, it's usually easiest to resolve by making an explicitly weak reference to self
for the block to use:
__weak MyObject *weakSelf = self;
[self setMyBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[weakSelf doSomethingWithObj:obj];
}];
But this should not be the default pattern you follow when dealing with blocks that call self
! This should only be used to break what would otherwise be a retain cycle between self and the block. If you were to adopt this pattern everywhere, you'd run the risk of passing a block to something that got executed after self
was deallocated.
//SUSPICIOUS EXAMPLE:
__weak MyObject *weakSelf = self;
[[SomeOtherObject alloc] initWithCompletion:^{
//By the time this gets called, "weakSelf" might be nil because it's not retained!
[weakSelf doSomething];
}];
Why passing a weak reference to a block prevents an object from being retained?
You can sort of think of a block as an object which has an "instance variable" for each captured variable, which is initialized with the value of the corresponding captured variable at the time the block is created.
In ARC, the block's "instance variables" have the same ownership specifier as the corresponding captured variable. So if a captured variable of object-pointer type is __strong
(the default), the block's "instance variable" is also __strong
, so it retains the object pointed to for the lifetime of the block. If a captured variable of object-pointer type is __strong
, the block's "instance variable" is also __weak
, hence it is a zeroing weak reference to the object pointed to.
Disappearing reference to self in a block under ARC
Here is essentially what your code is doing:
- Making a weak variable,
weakSelf
. - Passing a block to a function that references that weak variable.
A this point, self
is not retained by the block nor the weakSelf
variable. Then, when the block runs, weakSelf
is put into a __strong
variable, thus retaining any value that was in weakSelf
. Unfortunately, if the original value of weakSelf
, namely self
was already deallocated, weakSelf
would be nil
already.
The compiler can see what external variables your block accesses, and then adds any necessary retains if those variables are __strong
. The compiler does not care that you assign a __weak
variable to an internal variable that happens to be __strong
. This retain will happen when the block runs, not when it is created.
By using self
directly from the block, the compiler sees that you are referencing a variable that is not __weak
, and therefore automatically retains that variable for the lifecycle of the block. In cases like this, I see no reason why you wouldn't directly reference self in the block, unless you are worried about a circular retain cycle.
Weak Self in Blocks
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.
Does a reference remain weak if passed as an argument in objective-c?
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.
Weak self vs self when using closure defined in swift in objective c
First of all try to understand what is a retaincycle
and how it will affect your application..
A retain cycle
is a condition that happens when two objects keeps strong reference to each others.
In such cases these objects won't get deallocated and it will stay in memory forever and leads to memory leak.
Retain cycle in blocks and why should we use weakself
Closures and blocks are independent memory objects and they will retain the objects they reference so if we are accessing any class variable or method inside the closure or block using self
then there is a chance for retain cycle
self.myBlock = ^{ self.someProperty = xyz; };
// RETAIN CYCLE
will get this warning
Capturing 'self' strongly in this block is likely to lead to a retain
cycle
To avoid such situation we should weakSelf to access members
__weak typeof(self) weakSelf = self;
`self.myBlock = ^{ weakSelf.someProperty = xyz; };`
So there is a rule like always use weakSelf in blocks
but there are some special cases like animation blocks
[UIView animateWithDuration:duration animations:^{ [self.superview layoutIfNeeded]; }];
Here we can use self inside the block because the blocks get destroyed automatically once animation completed.
Is it necessary to use weak references to self always inside blocks..?
You should only use a weak reference to self
, if self
will hold on to a reference of the block.
In your example, you are not keeping a reference to your block in self
, you are only using blocks inline with the UIView animateWithDuration:
, and as such there is no need to use __weak myViewController *weakSelf = self;
Why is this the case? Because a block will retain strong references to any variables it uses from the class using the block. This includes self
. Now if the class instance itself keeps a strong reference to the block, and the block keeps a strong reference to the class instance, you have a retain cycle, which will cause memory leaks.
In Objective-c blocks, do I need to pass weak/strong self to helpers?
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 [self new] in a block creates strong reference cycle?
Will [self new] act like [MyType new] or a block will capture self?
As mentioned by the other answers, this is no retain cycle. However, keep in mind that self
points to the class object and class objects are not object of ARC: They have an eternal life time.
Is it a right way to create new instance of MyType using [self new]?
It is the better way. See below.
What are benefits of using [self new] instead of [MyType new]?
Inside the implementation of the class you should almost always use self
instead of MyType
. (But your code is one of the rare examples for having no advantage of doing so because of the static variable.)
The reason for this is, that code can be used by subclasses. If you put the concrete type in your code, every creation method has to be overwritten, which can lead to much code and triggers the broken base class problem.
Example:
@implementation BaseClass
+ (instancetype)new…
{
BaseClass *instance = [BaseClass new];
…
}
@end
@interfac Subclass : BaseClass
…
@end
This is broken, because …
id instance = [Subclass new…];
… would create an instance of the subclass.
You have to overwrite new…
, what has an additional problem:
@implementation Subclass
+(instancetype)new…
{
/* Subclass *instance = [super new]; Does NOT work*/
… Complete re-implementation of +new… (BaseClass)
}
Block in block, with __weak self
In this case (below) use just strong self
, because the block is copied just for those few seconds. And usually if you want the self
to perform block, you want to it to stay alive until that time, so strong reference is perfectly okay.
[self performBlock:^{
[self doSomething]; // strong is OK
} afterDelay:delay];
Block inside a block? In your case those two block are just delayed one-shot blocks, so the same as above, use strong. But there are differences between blocks. If you store the block for longer time, maybe for multiple invocations you should avoid retain-cycles.
Example:
self.callback = ^{
[self doSomething]; // should use weakSelf
};
This may cause retain-cycle. In fact it depends on how the block is used. We see that the block is stored (copied) in property for later use. However, you can prevent the retain-cycles by nullifying block that will not be used any more. In this case:
self.callback(); //invoke
self.callback = nil; //release
When using ARC, you don't have to copy blocks yourself. There were bugs in early versions after blocks were added, but now the compiler under ARC knows when to copy blocks. It is clever enough to copy it in this case:
[self performSelector:@selector(executeBlockAfterDelay:) withObject:block afterDelay:delay];
Related Topics
Uitableviewcell, Show Delete Button on Swipe
How to Handle Different Orientations in Ios
How to Upload Images to a Server in iOS With Swift
Xcode 6 - Xcassets For Universal Image Support
Uilabel - Auto-Size Label to Fit Text
How to Make an Http Request + Basic Auth in Swift
iPhone Reboot Programmatically
Set the Maximum Character Length of a Uitextfield in Swift
How to Add an In-App Purchase to an iOS Application
How to Compare Two Uiimage Objects
How to Animate the Background Color of a Uilabel
How to Change Multiplier Property For Nslayoutconstraint
How to Launch Safari and Open Url from iOS App