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.
Related
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.
Im doing some research on blocks,
the code here
typedef NSString* (^MyBlock)(void);
#property(copy,nonatomic) MyBlock block1;
in viewdidload
self.block1 = ^{
self
NSLog(#"do block");
return #"a";
};
of course the self is retained, then I do a
self.block = nil;
by checking the retain count of self, I found it reduced by 1, no retain cycle.
I believe this is the correct situation, the block retains self, when release the block, self gets released. retaincount reduced.
I made a litte change, and things coms strange:
make block a local variable.
in viewdidload
MyBlock block1 = ^{
self
NSLog(#"do block");
return #"a";
};
[block copy]; // retain count of self gets added.
[block release]; // retain count of sell still the same
why? I tried Block_release(), its the same. and when putting a local variable like NSArray in the block, the retain count fellows the same rule as self.
there must be some thing different inside of #property, anyone researched this before?
pls help.
Additionally, I do this in ARC, a local variable block will made the retain cycle, and a instance variable didnt, due to the autorelease, it holds the self, and few seconds later, it released and self object get released normally.
is it because the instance variable and local variable are alloc on different parts in memory? stack ? heap?, are they both copied to heap when do a [block copy]?
EDIT :
not instance variable and local variable. using #property makes it different, any explanations?
The problem is that using retainCount to figure out things like this is futile. The retainCount will not reflect autorelease state and the compiler -- the ARC compiler, in particular -- may generate different code (in particular, the optimizer has a tendency to eliminate unnecessary retain/autorelease pairs).
Use the Allocations Instrument and turn on reference event tracking. Then you can look at each retain/release event on the object, the exact stack trace where it happened, and know exactly what is going on.
Under non-ARC, when you assign to an iVar, nothing happens. When you go through the setter, a retain setter will cause the object to be retaind. Under ARC, a block will be copied to the heap automatically in a number of cases, triggering a retain of the captured object when the block is copied.
http://www.whentouseretaincount.com/
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 :)
Just trying to fully understand ARC.
MyView *testView = [[MyView alloc] init];
__weak MyView *weakView = testView;
[weakView addObserver:self forKeyPath:#"alpha" options:0 context:nil];
testView = nil;
if(weakView) {
NSLog(#"WeakView exists!");
}
I don't understand why my NSLog statement is printing. Since weakView is a weak reference to testView, shouldn't it be pointing to nil once testView is set to nil???
Thanks!
The addObserver method seems to retain and autorelease the view. Thats why the weak reference is not zeroed right after the initial reference is nilled. Just run this code in the debugger:
UIView *testView = [[UIView alloc] init];
__weak UIView *weakView = testView;
#autoreleasepool {
[weakView addObserver:self forKeyPath:#"alpha" options:0 context:nil];
}
testView = nil;
if(weakView) {
NSLog(#"WeakView exists!");
}
It may or may not. It goes to nil when the object is deallocated. The fact that you set testView to nil only implies that you are releasing the object. But the object is not guaranteed to immediately be deallocated.
The problem here is that you are assuming a given value for the retain count. You think that the alloc+init sequence gave you an object with a count of 1 so that when you set testView to nil it goes to 0 and the object is deallocated.
You should never assume a given retain count. You should always think in terms of relative retain counts. The alloc+init sequence returns a +1 object (not 1 but +1). When you set set testView to nil ARC calls release and turns it to a +0 object (not 0, but +0). This means you have no guarantee that it's still accessible. Your weak reference may or may not be valid.
What is in fact happening is that internally in the init method (or the chained init methods of the parents) there has been a call to autorelease therefore your object does not yet have a refcount of 0. It will get it (and be deallocated) at the next pool drain.
Edit:
Also what Adam says in his reply is correct.
Your testView is local variable and local variables under ARC doesn't have precise lifetime semantics. Read 6.1 at:
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#optimization.precise
What does it mean? This means that the compiler can do whatever it wants to do.
Current implementation releases testView object at the end of the method. But what if the optimizer (now, future, ...) decides that the lifetime is over and it will release it sooner (before the end of the method)?
In other words, you're trying to depend on undefined behavior. Don't do this, don't rely on this. In this case, you never know when the object is really released = weak reference is zeroed.
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.