Using method with self inside blocks - objective-c

I need to execute same bunch of code in two blocks (I'm using ARC):
__weak typeof(self) weakSelf = self;
[_dataProvider doA:^(NSError *error) {
[weakSelf handleError:error];
}];
And in a different place i call:
__weak typeof(self) weakSelf = self;
[_dataProvider doB:^(NSError *error) {
[weakSelf handleError:error];
}];
Then I have my handler:
- (void)handleError:(NSError *)error {
[self.refreshControl endRefreshing];
[self.tableView reloadData];
}
Is it save to use it this way? Please do notice that handleError: method uses self inside. If not, then what is the proper approach here? BTW: self is a viewController and can be dealloced (doB: and doA: blocks are based on networking, so can be slow).

It is not safe to do this, even if many people a doing it like this.
You should use the "weakSelf" pattern with blocks when it is justified.
In your example the "weakSelf" pattern is not justified, because self don't have any strong reference to your block. You can use like this :
[_dataProvider doA:^(NSError *error) {
// here you can use self, because you don't have any strong reference to your block
[weakSelf handleError:error];
}];
Use "weakSelf" pattern if you have a strong reference to your block ( with a property or an instance variable for example) and your are capturing self inside the block, example :
#property(strong) void(^)(void) completionBlock;
....
__weak typeof(self) weakSelf = self;
self.completionBlock = ^{
// Don't use "self" here, it will be captured by the block and a retain cycle will be created
// But if we use "weakSelf" here many times, it risques that it will be nil at the end of the block
// You should create an othere strong reference to the "weakSelf"
__strong typeof(self) strongSelf = weakSelf;
// here you use strongSelf ( and not "weakSelf" and especially not "self")
};

Related

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];
};

Will this hold self inside a block?

OK, this code on ARC holds self inside the block:
dispatch_async(someQ, ^{
[self doSomething];
});
and that can be solved by
__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
[weakSelf doSomething];
});
but what if doSomething has a lot of references to self? Because doSomething code will run inside the block isn't the same of all code of doSomething is on the block directly?
Do I need to pass weakSelf to doSomething so the method can use weakself references instead of self? Something like
__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
[weakSelf doSomethingUsingThisSelf:weakself];
});
By doing:
MyRequest *__weak weakSelf = self;
dispatch_async(someQ, ^{
[weakSelf doSomething];
});
...when there are no more references to self, weakSelf automatically becomes nil. So the async callback will end up sending doSomething to nil in the even the object is destroyed before the callback, which will do nothing.
If weakSelf is not nil, it's just a pointer to an object. When you send a selector to an object, there two implicit arguments: self and _cmd (see the documentation for IMP), section 6.1). So weakSelf becomes the implicit self in those calls. At that point, self is a strong reference, so the object won't get destroyed out from underneath you during the doSomething call chain, but referencing self from doSomething doesn't cause a reference count to increment because the block doesn't know anything about what goes on inside of doSomething.

What happens to weakSelf and strongSelf in a block when the same block is executed multiple times?

PREFACE
According to the Clang docs, "For __weak objects, the current pointee is retained and then released at the end of the current full-expression." Which to me indicates that if I do this:
__weak typeof(self) weakSelf = self;
[self doSomethingInBackgroundWithBlock:^{
if (weakSelf) {
[weakSelf doSomethingInBlock];
}
}];
NOTE
If you reference #dasblinkenlight's answer below, you'll notice that there is a possibility of weakSelf becoming nil before doSomethingBlock.
Assuming doSomethingInBlock, does start with weakSelf existing, the rest of it should run no problem and there's no risk of weakSelf becoming nil before it has finished executing. However, if I were to run this:
__weak typeof(self) weakSelf = self;
[self doSomethingInBackgroundWithBlock:^{
if (weakSelf) {
// Guaranteed to be retained for scope of expression
[weakSelf doSomethingInBlock];
// weakSelf could possibly be nil before reaching this point
[weakSelf doSomethingElseInBlock];
}
}];
The work around that is suggested is to take weakSelf and convert it to a strong variable inside of the block, like this:
__weak typeof(self) weakSelf = self;
[self doSomethingInBackgroundWithBlock:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomethingInBlock];
[strongSelf doSomethingElseInBlock];
}
}];
QUESTION
What happens to the weakSelf and strongSelf during multiple iterations of the same block? Is there a chance that in processBlock()(below), self could exist for some objects and not for others?
EXAMPLE
For example, if I were processing an array of objects in the background using something like this, where processBlock contains references to self:
- (void) processValuesInBackgroundWithArray:(NSArray *)array usingBlock:(void (^)(id))processBlock {
for (id ob in array) {
// Block is called for each Object
// Is there a chance that self will exist for some objects and not for others?
processBlock(ob);
}
}
Called like this:
__weak typeof(self) weakSelf = self;
[self processValuesInBackgroundWithArray:someArray usingBlock:^(id object) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[self doSomethingWithObject:object];
[self doSomethingElseWithObject:object];
}
}];
So the block references strongSelf from weakSelf, but the block is executed multiple times. Is there a chance that strongSelf might become nil in between iterations of objects in an array?
There is no guarantee that in your first example the weakSelf inside the if would be non-nil, because the block has two full expressions that reference it:
the if (weakSelf) check is the first full expression
the weakSelf in [weakSelf doSomethingInBlock]; invocation is the second one.
Therefore, your trick with strongSelf should be applied even when there is only one weakSelf invocation "protected" by the if statement.
Is there a chance that in processBlock()(below), self could exist for some objects and not for others?
Since there is no guaranteed __strong reference in a stack frame preceding the processValuesInBackgroundWithArray: call, self may become released between iterations of the loop, but only in a situation when the call of your last code snippet happens on a __weak or an unretained reference to the object containing the method from your last snippet.
Let's say that your last code snippet is inside a method called testWeak, in a class called MyClass:
-(void)testWeak {
__weak typeof(self) weakSelf = self;
[self processValuesInBackgroundWithArray:someArray usingBlock:^(id object) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[self doSomethingWithObject:object];
[self doSomethingElseWithObject:object];
}
}];
}
When the call is made like this
[myClassObj testWeak];
and myClassObj is __strong, the self object inside testWeak would be retained outside the call by the strong reference to myClassObj, so your code would be good, with or without the strongSelf trick.
When myClassObj is weak, however, and the last __strong reference gets released concurrently with the running loop, some objects inside the loop would end up seeing a nil weakSelf inside the block. The only difference that the strongSelf is going to make is preventing that doSomethingElseWithObject would be called on nil, while doSomethingWithObject would be called on a non-nil object.

Blocks with reference to self and instance vars

What's the correct way to reference 'self' (and ivars) within blocks without the block creating a strong reference (and thus incrementing the ref count)?
For instance, I've found the following increments the ref count for 'self':
^(id sender) {
[self.navigationController popViewControllerAnimated:YES];
}
In order to circumvent the above, I've been doing the following:
__weak WhateverController *weakSelf = self;
^(id sender) {
[weakSelf.navigationController popViewControllerAnimated:YES];
};
And yes, I realize this is pseudocode.
Also, an indirect reference to self also creates a retain on self. For example, if _ivar were an instance variable, accessing it is an implicit reference to self so the following would also retain self.
^(id sender) {
[_ivar popViewControllerAnimated:YES];
}
Furthermore, to expand on your weak example, it is OK to send a message to a weak reference. If it's nil, nothing will happen. If not, then the compiler will generate code that ensures the reference remains valid through the invocation of the method.
So, this is fine:
__weak Foo *weakSelf = self;
^(id sender) {
[weakSelf.foo doSomething];
}
because foo will either be nil or if not, it is guaranteed to remain non-nil throughout the execution of doSomething.
However, the following would be inadvisable because self could go to nil in-between calls, which is probably not what you want:
__weak Foo *weakSelf = self;
^(id sender) {
[weakSelf.foo doSomething];
[weakSelf.foo doSomethingElse];
}
In that case, you probably want to create your own strong reference inside the block, so you have a consistent value throughout the execution of the block.
On the other hand, if you access iVars directly through a weak reference, you must do the weak-strong dance because this code:
__weak Foo *weakSelf = self;
^(id sender) {
weakSelf->_foo = bar;
}
will blow up if weakSelf is nil.
Thus, in the last two situations above, you want to do something like:
__weak Foo *weakSelf = self;
^(id sender) {
Foo *strongSelf = weakSelf;
if (!strongSelf) return;
// Now, do anything with strongSelf, as it is guaranteed to be around
}
Of course, the iVar situation is only a problem if you actually access iVars directly...
Apple's notation is sself but other than that - you're fine.
In a non arc project use the following code to prevent 'self' from being retained by the block:
__block id sself = self

Nested blocks and references to self

I have a block wherein I use self so I declare a weak reference to self:
__weak MyClass *weakSelf = self;
Now my questions:
I get an error where I define weakSelf and I don't understand what this should mean.:
weak attribute can not be specified on an automatic variable
Inside my block I pass weakSelf to another block and I am not sure if I now have to do the same thing again like so:
__weak MyClass *weakWeakSelf = weakSelf;
And then pass weakWeakSelf to that block?
This is most likely occurring as you are targeting down to iOS 4. You should change it to be
__unsafe_unretained MyClass *weakWeakSelf = weakSelf;
With ARC
__weak __typeof__(self) wself = self;
Wihtout ARC
__unsafe_unretained __typeof__(self) wself = self;
With libextobjc it will be readable and easy:
- (void)doStuff
{
#weakify(self);
// __weak __typeof__(self) self_weak_ = self;
[self doSomeAsyncStuff:^{
#strongify(self);
// __strong __typeof__(self) self = self_weak_;
// now you don't run the risk of self being deallocated
// whilst doing stuff inside this block
// But there's a chance that self was already deallocated, so
// you could want to check if self == nil
[self doSomeAwesomeStuff];
[self doSomeOtherAsyncStuff:^{
#strongify(self);
// __strong __typeof__(self) self = self_weak_;
// now you don't run the risk of self being deallocated
// whilst doing stuff inside this block
// Again, there's a chance that self was already deallocated, so
// you could want to check if self == nil
[self doSomeAwesomeStuff];
}];
}];
}