iOS block release and self retain cycle - objective-c

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/

Related

Objective-C: Should we use weak self within block or assign weak self to strong before using it?

As we know, using strong self within a block can lead to retain cycles and memory leak. Is the common practice to use weak self in a block, or is it better to assign the weak self to strong within the block and then use it as such so the weak self is not released during block execution? Does it matter since weak self will be zero-ed out anyway?
Due to the volatile nature of weak variables, you should use them with care. If you are using weak variables in a multithreading environment, it is considered good practice to assign the weak variable to a strong one and check for nil before using. This will ensure that the object will not be released in the middle of your method, causing unexpected results.
Consider the following case:
__weak id var;
//...
if(var != nil)
{
//var was released here on another thread and there are not more retaining references.
[anotherObj performActionWithAnObjThatMustNotBeNil:var]; //<- You may crash here.
}
The compiler can be configured to throw a warning on a consecutive access of a weak variable.
On the other hand, if your use is in the main thread, and all calls to the object are on the main thread, this problem is moot, since the object will either be released before the block call or after, thus it being safe to access the weak variable directly.
There are two possible questions here that are easy to get confused:
Is it possible for a __weak reference to become nil in the middle of a method?
id __strong strongObject = ...;
id __weak weakObject = strongObject;
dispatch_async(dispatch_get_main_queue(), ^{
[weakObject method1]; // if weakObject is non-nil here
[weakObject method2]; // can it become non-nil here?
});
Yes! Xcode will even warn you about it.
Is it possible for self to become nil in the middle of a method if the method is called on a __weak lvalue as below?
id __strong strongObject = ...;
id __weak weakObject = strongObject;
dispatch_async(dispatch_get_main_queue(), ^{
// is it possible for weakObject to be deallocated
// while methodUsingSelf is being called?
[weakObject methodUsingSelf];
});
- (void)methodUsingSelf {
NSLog(#"%#", self); // Could this be non-nil
NSLog(#"%#", self); // while this is nil?
}
No! Joe Groff, of the Swift team at Apple, said so:
self is guaranteed kept alive by ObjC ARC while a method on self is
executing.
Clang's official ARC documentation covers this case in the Semantics/Reading subsection:
Reading occurs when performing a lvalue-to-rvalue conversion on an
object lvalue.
For __weak objects, the current pointee is retained and then released
at the end of the current full-expression. This must execute
atomically with respect to assignments and to the final release of the
pointee.
Thus, calling a method on a __weak variable, is roughly equivalent to the following Manual Retain/Release (MRR) code:
id retainedObject = ...;
id assignedObject = strongObject;
dispatch_async(dispatch_get_main_queue(), ^{
{
[assignedObject retain];
[assignedObject methodUsingSelf];
[assignedObject release];
}
});
Of course, in MRR, [assignedObject retain]; might crash because the object assignedObject points to might have been deallocated, so assignedObject might point to garbage. ARC doesn't have this problem because it zeroes weak references.
I think that even if using the weak will work and be retained as long as needed, assigning it to strong before using will make it more readable and "worries free"...:
__weak id weakThing = thing;
thing.someBlock = ^{
if (weakThing) {
id strongThing = weakThing;
strongThing doThisWithThat...
}
};
Compiler won't complain and it is safe and maybe not less importantly - easy to understand for John Doe who will try to read this code tomorrow....
You can continue to use the weak self. The only time you'd need to use strong self is if you are trying to access a self->ivar directly, instead of going through a property.

Blocks and extra retains

When ARC enabled, following code causes the obj retained twice for the block by calling objc_retain() and objc_retainBlock().(So retainCount becomes 3 after the block definition.)
I checked that obj is not in autorelease pool and there are two objc_release() calls for obj at the end of the method. (I know counting retains does not make sense but i am checking the objc_retain() calls, not barely checking retain counts.)
What is the rationale behind this?
-(void)myMethod
{
NSObject *obj = [[NSObject alloc] init];
NSLog(#"obj %# retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
void (^myBlock)(void) = ^()
{
NSLog(#"obj %# retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
};
NSLog(#"obj %# retaincount %ld", obj, CFGetRetainCount((__bridge CFTypeRef)obj));
myBlock();
}
Isn't it enough to retain the obj just once for capturing it by the block?
Note: Also, when i remove the myBlock variable and the call for it, so just with ^() {...} definition and that definition could never be called, obj is still retained with objc_retain() which seems weird. I am using XCode 4.3.2.
www.whentouseretaincount.com -- i.e. don't use retainCount as it'll cause nothing but confusion. Even for learning the innards.
If you want to know how and when blocks retain objects, you should look at the compiler, runtime, and blocks runtime sources. All are available.
A block may or may not retain an object. Specifically, a block may only retain an object when the block is copied (as long as the object reference isn't __weak).
Similarly, but orthogonally, ARC's retain/release behavior changes based on the optimization level of the compiler. In particular, DEBUG (-O0) code tends to have lots of retain/release. -Os (optimized) code will have many of these optimized out.
Please read this: http://whentouseretaincount.com/
You shouldn't use retain count, the apple developers who wrote it advise against it, a lot of smart people advise against it and i'm telling you not to use it.
As for retain cycles its good practice to have a weak property outside of your block scope as such:
__weak typeof(obj) weakObj = obj;
void (^block)(void) = ^{
[weakObj method];
};

code blocks with Grand Central Dispatch

I'm writing an app using ARC, and I'm wondering if the following will cause a problem. Specifically, I'm creating an object 'A', then using GCD I add a code block to the main thread's queue and in the code block I perform some operations on the weak reference to the object. But by the time the code block is executed, my object has already been nullified. Since the code block only has a weak reference to the object, will this cause a problem? Or does the compiler somehow know to keep a reference to the object since my code block needs it when it runs?
Foo *A = [[Foo alloc] init];
__weak Foo *weakA = A;
dispatch_async(dispatch_get_main_queue(), ^{
//...do something here with weakA
});
A = nil;
Thanks!
Why are you using __weak here? If you want the block to "keep a reference to the object since [your] code block needs it when it runs", then you don't need to do anything:
Foo *a = [[Foo alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
[a something];
});
In the above snippet, the block retains a, so it will exist when the block executes.
As this question explains, the only time you need to use __weak with blocks is to break retain cycles that occur when the block itself is going to be retained. For example:
__weak Foo *someObject = [bar getAFoo];
[someObject doSomeTaskWithCompletionHandler:^{
[someObject doSomethingElse];
}];
Here, if someObject were not declared to be __weak, then you would have a retain cycle since someObject would presumably retain the block (since it would need to keep the block until it was done doing some task), and the block retains someObject. Using __weak here tells the block not to retain someObject, so the error doesn't occur. And you don't need to worry about someObject being nil when the block executes, because someObject owns the block. (If someObject were to be deallocated, then the block wouldn't be executed).
This is an interesting question with some subtleties.
You've explicitly told the compiler to disregard the reference from within the block by tagging it as __weak, so this code is not sufficient to keep the object alive until the block has been executed. It sounds like you're clear on that already, though.
Normally, a weak reference such as weakA would be nullified when the object it refers to is deallocated. However, weakA is a stack variable, so when it's referred to in a block, the block receives a const-ified version of it that memorializes its value at the time of the block's creation. Presumably, this const copy of weakA can't be nullified. See this section of the Apple docs for more on this.
If you change the declaration of weakA to
__block __weak Foo *weakA = A;
then weakA is promoted off the stack and is writable both from its original context and from the block. It still won't keep the referred-to object alive on its own, but at the point of the block's execution you can check to see if its value is nil.
More details on __block can be found here - skip down to the section "ARC Introduces New Lifetime Qualifiers".

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.

Should I retain a object pointer parameter in every method?

I am trying to get the hang of retain / release. I get that they are a matched set. But I don't know when I have to retain references.
-(void)sampleMethod:(RandomClass *) obj {
[obj retain];
// Do stuff to object...
[obj release];
}
Is it necessary to retain (and thus release) obj?
I am worried about obj going away. Does it follow that you must (if) retain reference parameters as soon as possible in the function? What about the space of time between the functions call and the first instruction of the function?
Thanks!
Short answer; use ARC.
Joe's answer is more or less correct. Until it isn't.
In general, there is no need to retain arguments or return values from other methods. However, the resulting code only works by coincidence and convention, not by algorithmic analysis.
Consider:
NSString *foo = [aMutableArray objectAtIndex: 5];
[aMutableArray removeObjectAtindex: 5];
[someTextField setTextValue: foo];
BOOM!
Your code just crashed. Maybe (it won't crash if foo happens to be a constant string or happens to have been retained by something else or happens to have been retain/autoreleased somewhere else).
Technically, that should be:
NSString *foo = [aMutableArray objectAtIndex: 5];
[foo retain];
[aMutableArray removeObjectAtindex: 5];
[someTextField setTextValue: foo];
[foo release];
That is, foo should be retained the moment it comes into scope and released the moment it is no longer used in a scope. Or you could [[foo retain] autorelease];, but autorelease pressure can be a problem (it generally isn't, but it can be).
ARC does this kind of analysis and would ensure that foo is retained as shown above when necessary.
You do not have to worry about the object being passed going away so there is no need to retain it. Proper memory management* ensures that the object will live for the duration of your method because it will be within the same thread as the caller, therefore the autorelease pool for that thread should not be drained and the caller can not release the object until your method has returned. This even holds true with methods such as performSelectorInBackground because that will retain the argument.
*Proper memory management - This means each thread that uses auto released objects gets it own autorelease pool that is drained within the same context it is created and objects passed across threads are properly retained.