block in block cause self be retained, __block not work - objective-c

Add: the problem happen when I copy the block inside the function:
[block copy]
I am already using __block to avoid retain self.
__block typeof(self) bself = self;
However, when there is another block in this block, and it use bself, self will still be retained.
As show in code below, the first bself will not retain self as expected. However, the 2nd bself will retain self.
__block typeof(self) bself = self;
[layer start:param1
completeHanlder:^{
bself.xx = localxx;
dispatch_async(dispatch_get_main_queue(), ^(void) {
... ...
[bself something];
});
}
];
anyone know reason behind ?

You are doing wrong but concept it's right, here the error:
__block
This is used to let a strong reference inside your block. You could for example change value outside your block.
The right way is doing with __weak that will receive a weak reference from your instance and prevent strong loop reference like this:
__weak typeof(self) bself = self;
And because __block that you created retain and strong reference :)

Related

Using __block and __weak

I've read over this thread: What does the "__block" keyword mean? which discusses what __block is used for but I'm confused about one of the answers. It says __block is used to avoid retain cycles, but the comments underneath it leave me unsure.
I'm using it something like this:
self.someProperty = x; //where x is some object (id)
__block __weak VP_User *this = self;
//begin a callback-style block
this.someProperty = nil;
Do I need to use both __block and __weak? Any glaring problems with this way this looks?
__block is a storage qualifier. It specifies that the variable should directly be captured by the block as opposed to copying it. This is useful in case you need to modify the original variable, as in the following example
__block NSString *aString = #"Hey!";
void(^aBlock)() = ^{ aString = #"Hello!" }; // without __block you couldn't modify aString
NSLog(#"%#", aString); // Hey!
aBlock();
NSLog(#"%#", aString); // Hello!
In ARC this causes the variable to be automatically retained, so that it can be safely referenced within the block implementation. In the previous example, then, aString is sent a retain message when captured in the block context.
Note that this isn't true in MRC (Manual Reference Counting), where the variable is referenced without being retained.
Marking it as __weak causes the variable not to be retained, so the block directly refers to it but without retaining it. This is potentially dangerous since in case the block lives longer than the variable, since it will be referring to garbage memory (and likely to crash).
Here's the relevant paragraph from the clang doc:
In the Objective-C and Objective-C++ languages, we allow the __weak specifier for __block variables of object type. [...] This qualifier causes these variables to be kept without retain messages being sent. This knowingly leads to dangling pointers if the Block (or a copy) outlives the lifetime of this object.
Finally the claim that __block can be used to avoid strong reference cycles (aka retain cycles) is plain wrong in an ARC context. Due to the fact that in ARC __block causes the variable to be strongly referenced, it's actually more likely to cause them.
For instance in MRC this code breaks a retain cycle
__block typeof(self) blockSelf = self; //this would retain self in ARC!
[self methodThatTakesABlock:^ {
[blockSelf doSomething];
}];
whereas to achieve the same result in ARC, you normally do
__weak typeof(self) weakSelf = self;
[self methodThatTakesABlock:^ {
[weakSelf doSomething];
}];
You should use __block if you want to change variable value in block.
e.g:
__block BOOL result = NO;
dispatch_sync(dispatch_get_main_queue(), ^{
...
result = YES;
...
});
You should use __weak if you want to avoid retain cycles.
e.g.:
__weak typeof(self) wself = self;
self.foobarCompletion = ^{
...
wself.foo = YES;
...
};
You can combine them if there is a need.

Avoiding the "capturing self strongly in this block is likely to lead to a retain cycle" message

every time I have to use a global var or property inside a block like this:
self.save = ^(){
if (isItSaving == NO) {
[self saveMyFile];
}
};
I have to rewrite this like
BOOL *iis = isItSaving;
id myself = self;
self.save = ^(){
if (iis == NO) {
[myself saveMyFile];
}
};
or Xcode will complain "capturing self strongly in this block is likely to lead to a retain cycle...
It complains even about BOOL variables?
Redeclaring everything before a block appears to be a lame solution.
Is this the correctly way? Is there an elegant way?
This stuff is ugly. I am using ARC.
The problem only occurs when referencing self from within the block, explicitly or implicitly. There's no warning emitted when accessing global variables.
In your case you probably accessed a (boolean) ivar. Accessing the ivar implicitly uses self, that's why the compiler is warning you (correctly) about a retain cycle.
The common way to fix the retain cycle is:
typeof(self) __weak weakSelf = self;
self.save = ^() {
typeof(weakSelf) __strong strongSelf = weakSelf;
if (strongSelf != nil && ! strongSelf->isItSaving) {
[strongSelf saveMyFile];
}
};
... and, yes, that's a bit of an ugly part of blocks.
Use __unsafe_unretained typeof(self) weakSelf = self;
In addition to #NikolaiRuhe's response, in your example when declaring the properties
BOOL *iis = isItSaving;
id myself = self;
implies strong references, so use __weak self to prevent the retain cycle. Then you might wonder why you need to declare a __strong reference to weak self within the block, and that's to make sure it doesn't get released during the life of the block, otherwise weakSelf->isItSaving would break if self was released.

Why do we have to set __block variable to nil?

From the Transitioning to ARC Release Notes
Use Lifetime Qualifiers to Avoid Strong Reference Cycles
You can use lifetime qualifiers to avoid strong reference cycles. For
example, typically if you have a graph of objects arranged in a
parent-child hierarchy and parents need to refer to their children and
vice versa, then you make the parent-to-child relationship strong and
the child-to-parent relationship weak. Other situations may be more
subtle, particularly when they involve block objects.
In manual reference counting mode, __block id x; has the effect of not
retaining x. In ARC mode, __block id x; defaults to retaining x (just
like all other values). To get the manual reference counting mode
behavior under ARC, you could use __unsafe_unretained __block id x;.
As the name __unsafe_unretained implies, however, having a
non-retained variable is dangerous (because it can dangle) and is
therefore discouraged. Two better options are to either use __weak (if
you don’t need to support iOS 4 or OS X v10.6), or set the __block
value to nil to break the retain cycle.
Okay, so what's different about __block variable?
Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting.
MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
[myController release];
}];
As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:
MyViewController * __block myController = [[MyViewController alloc] init…]; //Why use __block. my controller is not changed at all
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil; //Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
};
Also why myController is not set to nil by compiler. Why do we have to do so? It seems that the compiler sort of know when myController will no longer be used again namely when the block expire.
When you have code of this form:
object.block = ^{
// reference object from inside the block
[object someMethodOrProperty];
};
object will retain or copy the block you give to it. But the block itself will also retain object because it is strongly referenced from within the block. This is a retain cycle. Even after the block has finished executing, the reference cycle still exists and neither the object nor the block can be deallocated. Remember that a block can be called multiple times, so it cannot just forget all the variables it references after it has finished executing once.
To break this cycle, you can define object to be a __block variable, which allows you to change its value from inside the block, e.g. changing it to nil to break the cycle:
__block id object = ...;
object.block = ^{
// reference object from inside the block
[object someMethodOrProperty];
object = nil;
// At this point, the block no longer retains object, so the cycle is broken
};
When we assign object to nil at the end of the block, the block will no longer retain object and the retain cycle is broken. This allows both objects to be deallocated.
One concrete example of this is with with NSOperation's completionBlock property. If you use the completionBlock to access an operation's result, you need to break the retain cycle that is created:
__block NSOperation *op = [self operationForProcessingSomeData];
op.completionBlock = ^{
// since we strongly reference op here, a retain cycle is created
[self operationFinishedWithData:op.processedData];
// break the retain cycle!
op = nil;
}
As the documentation describes, there are a number of other techniques you can also use to break these retain cycles. For example, you will need to use a different technique in non-ARC code than you would in ARC code.
I prefer this solution
typeof(self) __weak weakSelf = self;
self.rotationBlock = ^{
typeof (weakSelf) __strong self = weakSelf;
[self yourCodeThatReferenceSelf];
};
What happens is that the block will capture self as a weak reference and there will be no retain cycle. self inside the block is then redefined as __strong self = weakSelf before your code runs. This prevents self from being released while your block runs.

Will self retain within block?

Before/After call the block, the retaincount is always 1.
From apple block doc we know that the self should retain. Can anyone know why?
NSLog(#"Before block retain count: %d", [self retainCount]);
void (^block)(void) = ^(void){
UIImage* img = [UIImage imageNamed:#"hometown.png"];
[self setImage:img];
NSLog(#"After block retain count: %d", [self retainCount]);
};
block();
First, retainCount is useless. Don't call it..
Blocks only retain captured objects when the block is copied. Thus, self won't be retained by the block in that example.
OK I did some research, now things became more clear. firstly, I didn't use #property on block1, which means when I set it, nothing is copied, so they are not retained, secondly, if we do a [block copy], the variables will be retained, if we dont copy, the block points to a stack address, copy it to heap to make it safe.
the variable 'array' is a Member variable, so it's not retained and meanwhile the self will be retained, whether you put it in the block or not, if the variable is a local variable, it will be retained. ( this is the thing that Im still confused abt, why the member variable is not retained,instead the self is added one more on retain count??? pls answer me?)
after using the block we could set it to nil self.block = nil; to make variables released, and avoid the retain cycle.
PS. a method to break retain cycle is use __block id weakSelf = self; in the block, so it means __block variables are also not retained.

Disappearing reference to self in a block under ARC

I'm having trouble figuring out why a __weak reference to self is disappearing in the following block. Following Jiva's advice found here
http://blog.random-ideas.net/?p=160 I make a __weak reference to self outside the completion block, then make a strong reference to that weak reference within the block to hold on to it for the duration of the block.
The problem I'm having is that the weak reference (weakSelf) comes up nil when the block executes, but if I just make the call to self directly in the block everything works.
- (void)fetchItemList:(NSArray *)itemList withHandler:(ItemFetchCompletion)completionHandler
{
NSString *fetchString = [self fetchRequestUsingItemList:itemList];
NSURL *fetchUrl = [NSURL URLWithString:fetchString];
ASIHTTPRequest *itemListRequest = [ASIHTTPRequest requestWithURL:fetchUrl];
__weak FetchManager *weakSelf = self;
__weak ASIHTTPRequest *itemListRequestWeakRef = itemListRequest;
[itemListRequest setCompletionBlock:^{
ASIHTTPRequest *itemListRequestStrongRef = itemListRequestWeakRef;
ZAssert(weakSelf, #"weakSelf reference is nil.");
FetchManager *strongSelf = weakSelf;
NSData *fetchedData = [itemListRequestStrongRef responseData];
NSArray *fetchedItems = [strongSelf itemsFromFetchedData:fetchedData];
completionHandler(fetchedItems);
}];
[itemListRequest startAsynchronous];
}
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.