Why need weak self in block? [duplicate] - ios

This question already has answers here:
WeakSelf in blocks
(2 answers)
How do I avoid capturing self in blocks when implementing an API?
(8 answers)
Closed 7 years ago.
Just like the following code:
__weak typeof(self) weakSelf = self;
[self methodThatTakesABlock:^ {
[weakSelf doSomething];
//[self doSomething];//Why not this line?
}];

[self methodThatTakesABlock:^ {
[self doSomething];
}];
Does not cause a retain cycle unless the completion block is stored within self. If it is a property then, self will have a strong reference to the block and the block will have a strong reference to self causing a retain cycle. That is why you need to use weak, to avoid this retain cycle. But remember, you must use a weak self only within blocks that are stored as properties or ivars within self.
If the completion block is only called in the methodThatTakesABlock then you don't have to use a weak self since the block is not retained. In this case, the block will have a strong reference to self but self will not have one towards the block, so no retain cycle in this case.

Related

Weak self vs self when using closure defined in swift in objective c

Let say :-
I have a ViewController created in objeticve - c (Number.m).
I have a TableViewCell created in swift which contains button (CalculateSum.swift)
Now i need to tell VC that button has been tapped and send tag of the button. For this i use closure.
Swift :-
var calculateSumBtnTapped: ((UITableViewCell) -> Void)?
#IBAction func calculateSumBtnDidTapped(_ sender: Any) {
self.calculateSumBtnTapped?(self)
}
Now as we see CalculateSum.swift holds strong reference to calculateSumBtnTapped property.
Now i call this closure as block in Number.m
CalculateSum * calculateSum = [tableView dequeueReusableCellWithIdentifier:#"sum" forIndexPath:indexPath];
__block typeof(self) weakSelf = self;
calculateSum.calculateSumBtnTapped = ^(UITableViewCell * _Nonnull calculateSumCell) {
// calculating sum by tag
weakSelf.sum = weakSelf.sum + calculateSumCell.tag
};
Is it necessary to use self as weakself ? or I can use self as it is ?
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.
When an object A reference another object B strongly and object B references object A strongly, ARC cant dealloc there two objects thus creating retain cycle which may increase the memory footprint of your app and may cause app to crash. To avoid retain cycle one of the reference should be weak. Thats why you need to use weakSelf inside the block.

strongSelf pointing to weakSelf in a block, why? [duplicate]

This question already has answers here:
Strong reference to a weak references inside blocks
(2 answers)
Closed 6 years ago.
I am trying to understand this code :
__weak LoginViewController *weakSelf = self;
NSTimer *networkTimer = [NSTimer pym_scheduledTimerWithTimeInterval:15.0 block:^{
LoginViewController *strongSelf = weakSelf;
[strongSelf timeout];
} repeats:NO];
[PYMAuthManager loginWithUsername:username password:password completionHandler:^(BOOL successful) {
if (successful) {
[networkTimer invalidate].......
it's for a network timer, that will timeout after 15 seconds if no activity. Why is the pointer *strongSelf = weakSelf created in the block? Is it not okay just to use [weakSelf timeout]? I understood that whenever accessing self in a block we have to use a weak reference, why is another pointer created here? Any help would be great, thank you.
Edit: Updated to better reflect actual system semantics (as pointed out by Darren).
By using weakSelf in the block, you are avoiding retain cycles. If you were to replace the block code with [weakSelf timeout], there would be no difference; the object is retained for the duration of the timeout execution.
If you had instead used __unsafe_unretained to create your weakSelf, it's possible that the machine could release the memory back to the system and cause your app to EXC_BAD_ACCESS while executing timeout. Creating a strong reference in this instance would avoid this error.
When you create a strong reference, it is held within its scope; in this case, for the duration of the block. Because your block only effectively executes one statement, the replacement to [weakSelf timeout] causes no harm. If you had multiple statements that all used weakSelf or relied on the state of weakSelf, then you would want to create a strong reference for the scope of all of the statements.

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).

When is reference to self in block a retain cycle?

I've got a problem that is probably fairly common. In an ARC environment, a block that needs to reference self will outlive self. I'm aware of the convention to use __weak typeof(self) weakSelf = self; in blocks to avoid retain cycles. The problem is that we do need to retain self. So my question is: When does a reference to self in a block create a retain cycle? This post post suggests that in animation blocks, reference to self is ok.
I had also considered a solution like the following, but am not sure it changes anything:
__block typeof(self) blockSelf = self;
[someObj someMethodTakingCallback:^{
//do some stuff
blockSelf = nil;
}];
You get a reference cycle if self retains the block in addition to the block retaining `self.
In this case you would have a retain cycle if self holds a reference to someObj since someObj is probably holding a reference to self. It's actually a retain cycle if there's any retaining reference path from self to someObj.

Referring to weak self inside a nested block

Suppose I already create a weak self using
__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
...
}];
Inside that block, if I nest another block:
[weakSelf doAnotherBlockOperation:^{
[weakSelf doSomething];
}
will it create a retain cycle? Do I need to create another weak reference to the weakSelf?
__weak typeof(self) weakerSelf = weakSelf;
[weakSelf doAnotherBlockOperation:^{
[weakerSelf doSomething];
}
Your code will work fine: the weak reference will not cause a retain cycle as you explicitly instruct ARC not to increase the retainCount of your weak object. For best practice, however, you should create a strong reference of your object using the weak one. This won't create a retain cycle either as the strong pointer within the block will only exist until the block completes (it's only scope is the block itself).
__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
...
}
}];
It depends.
You only create a retain cycle if you actually store the block (because self points to the block, and block points to self). If you don't intend to store either of the blocks, using the strong reference to self is good enough --- block will be released first after it got executed, and then it will release it's pointer to self.
In your particular example, unless you're performing more operations which are not shown, you don't need to create any weakerWeakerEvenWeakerSelfs.

Resources