ARC __block behavior equivalent in MRC? - objective-c

As you know, in ARC, __block variables of object pointer type used in a block are retained by the block. So take the following simplified example:
__block id foo = getObject();
void (^aBlock)() = ^ {
NSLog(#"%#", foo);
foo = getObject();
}
runBlockAsynchronouslyMultipleTimes(aBlock);
The object pointed to by foo is retained by the block, so that when the block is run (asynchronously), the object is still valid and can be printed. When we do the assignment within the block, ARC manages it like any other strong reference (the old value is released and the new value retained). (The assignment forces us to use __block in the first place.) And when the block is not needed anymore, ARC somehow releases its retained object pointed to by foo at that point (it is not leaked).
Okay, now suppose I want to do the same thing under MRC (why is not important; this is an question about the language). As you know, __block variables of object pointer type used in a block are NOT retained by the block in MRC. Which is fine; we'll manage it ourselves (this is MRC, after all). So the attempt looks like this:
__block id foo = [getObject() retain];
void (^aBlock)() = ^ {
NSLog(#"%#", foo);
[foo release];
foo = [getObject() retain];
}
runBlockAsynchronouslyMultipleTimes(aBlock);
// where to release foo?
Most of it is straight-forward -- the object is retained by us initially manually; inside the block, when we re-assign the pointer, we release and retain the new value as appropriate.
But then comes the problem: How do we release the object when the block is not needed anymore? Since we manually manage the memory, we should ideally manually release the object when the block is deallocated. But there doesn't seem to be an easy way to do so.
I could think of maybe one way: using associative references to tie the object to the block. But then to re-assign the associative reference inside the block, the block would need a reference to itself, so the block variable would also need to be __block and the block needs to be copied prior to setting the variable. Which is all very ugly. Or, we put the object inside a mutable container object that is then retained by the block; but that is ugly too.

The mutable container is about as clean as you can get. You could create a simple wrapper with a single object property to clean it up a little, and then you would get memory management from the property accessors.
An approach which would look cleaner, but is actually kind of messy underneath, would be to have an immutable wrapper which took a pointer, and just released that pointer when it was deallocated.
#interface ObjectReleaser : NSObject {
id *objectPointer;
}
- (id)setObjectPointer:(id *)pointer;
- (void)captureMe;
#end
#implementation ObjectReleaser
- (void)setObjectPointer:(id *)pointer {
if(!objectPointer && pointer) {
objectPointer = pointer;
[*objectPointer retain];
}
}
- (void)dealloc {
if(objectPointer) [*objectPointer release];
[super dealloc];
}
- (void)captureMe {} // Blocks can call this to capture the object
#end
The block would catch and retain this object, since it is not __block. You would modify your __block object as usual, with all of the proper retains and releases. Then, when the block is deallocated, it will release the releaser, which will then be deallocated and release whatever your pointer currently points to.
__block id foo = getObject();
ObjectReleaser *releaser = [[ObjectReleaser alloc] init];
void (^aBlock)() = ^ {
[releaser captureMe];
NSLog(#"%#", foo);
[foo release];
foo = [getObject() retain];
}
aBlock = [aBlock copy];
[releaser setObjectPointer:&foo];
Note that you don't need to retain foo just for the block, because the releaser does that for you. You do have to set the releaser's pointer after copying the block, since the copy will change foo's pointer. This is also why it is safe to save the pointer of a stack variable after your function returns: the variable is not actually on the stack.

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.

Why do I need to set static pointer to nil before reassigning in this case

I have a "always keep a static reference on the last created object" pattern for one of my classes.
When I create a new instance of it, the static pointer should been set to this new instance.
Solved the way below:
static AViewController *actualSelf = nil;
+ (AViewController *) getActualSelf {
return actualSelf;
}
- (AViewController *) init {
self = [super init];
self.title = #"Title";
actualSelf = nil; // Why do I need this line the second time init gets called?
actualSelf = self; // this is the only line which sets actualSelf
return self;
}
- (void)dealloc {
actualSelf = nil;
}
…SOME IMPORTANT MUST BE MISSING, BUT I DON'T KNOW WHAT
create AViewController a > Init gets called > Static pointer is set to a
create AViewController b > Init gets called > Static pointer should be set to b. But the static pointer is not set to b! It's sets itself from a to nil!
Object a is most of the time deallocated before b gets created.
Do I always need to reset the static variables to nil when deallocating them? NO, see my own answer below.
Without the line "actualSelf = nil;", through ARC object a gets deallocated in the moment actualSelf is set to object b.
actualSelf = nil; // WHY DO I NEED THIS LINE?
You don't need the line, it accomplishes nothing and will probably be eliminated by the compiler optimizer in a release build.
The class is not a singleton.
The rest of the answer has been deleted because the question has been modified.
create AViewController a > Init gets called > Static pointer is set to a
create AViewController b > Init gets called > Static pointer should be set to b. But the static pointer is not set to b! It's sets itself
from a to nil!
Probably nothing other than actualSelf has ownership of a. Therefore, actualSelf = self; during the initialization of b causes a to be fully released and thus deallocated. During the -dealloc of a, it sets actualSelf to nil. Apparently, this is coming after the assignment of actualSelf to the new self (object b). (The precise order of operations of the ARC-supplied -release call vis-a-vis the assignment of actualSelf is unpredictable.)
The very fact that you are assigning actualSelf to nil in the -dealloc method smells bad. It suggests that actualSelf should be __weak because if it's holding a strong reference to an object, then that object can't be deallocated.
At the very least, -dealloc should test if actualSelf equals self before resetting it. But that will never be true so long as actualSelf is a strong reference, since a strongly referenced object can't be deallocated.
This whole approach is deeply problematic. What are you really trying to accomplish?

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.

How can code inside an Objective-C block reference the block object itself?

self is merely a captured variable inside a block and doesn't reference the block itself, so how does a block reference itself without having an explicit captured variable for that purpose?
__block void(^strawberryFields)();
strawberryFields = [^{ strawberryFields(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
strawberryFields);
you use the __block because the block will make a copy of the value of strawberryFields when the block is created which will be before the assignment.
you also must copy the block prior to any other copy operation or else you'll end up with a block that references the on-stack original version.
note that the above code leaks the block. Somewhere, there needs to be a release of that block to balance the copy.
I found this pattern to work and stable for ARC (automatic reference counting), both in Debug and Release builds.
-(void) someMethod
{
// declare a __block variable to use inside the block itself for its recursive phase.
void __block (^myBlock_recurse)();
// define the block
void (^myBlock)() = ^{
// ... do stuff ...
myBlock_recurse(); // looks like calling another block, but not really.
};
// kickstart the block
myBlock_recurse = myBlock; // initialize the alias
myBlock(); // starts the block
}
Initially I tried just putting a __block modifier to myBlock and use that variable directly to recurse within the block's implementation. That works on the ARC Debug build but breaks with an EXC_BAD_ACCESS on the Release build. On the other hand removing the __block modifier raises a "variable not defined when captured by block" warning (and I was reluctant to run it and test).
I have never tried this before and not 100% sure it's useful, if valid, but for example:
typedef void (^BasicBlock)(void);
__block BasicBlock testBlock;
testBlock = ^{NSLog(#"Testing %p", &testBlock);};
testBlock();
You probably have declare the variable with __block to prevent self-retain cycle.
The block needs some way to nil out its own reference. Typically it is done by storing the block in a property of the class.
Sometimes you can prefer to not use a property. Here is how you do it without a property:
__weak id weakSelf = self;
__block id block = ^{
if(weakSelf) {
// .. do whatever
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
else {
block = nil;
}
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC), dispatch_get_main_queue(), block);
The key thing to keep in mind is that all code paths must lead to a block = nil. We do that here by calling the block every 5 seconds until weakSelf turns nil.
Note that in ARC, it's a little different -- __block object pointer variables are by default retained in ARC, unlike in MRC. Thus, it will cause a retain cycle. It is necessary for the block to capture a weak reference to itself (using __weak) in order to not have a retain cycle.
However, we still need a strong reference to the block somewhere. If there are no strong references, the block (which is on the heap since it's copied) will be deallocated. Thus, we need two variables, one strong and one weak, and inside the block use the weak one to reference itself:
__block __weak void(^weakBlock)();
void(^myBlock)();
weakBlock = myBlock = [^{ weakBlock(); } copy];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
myBlock);

NSString no 'assign', 'retain', or 'copy' attribute is specified

I'm declaring an NSString property in a class and objective-c is complaining that:
NSString no 'assign', 'retain', or 'copy' attribute is specified
It then casually lets me know that "assign is used instead".
Can someone explain to me the difference between assign, retain and copy in terms of normal C memory management functions?
I think it is drawing your attention to the fact that a assign is being used, as opposed to retain or copy. Since an NSString is an object, in a reference-counted environment (ie without Garbage Collection) this can be potentially "dangerous" (unless it is intentional by design).
However, the difference between assign, retain and copy are as follows:
assign: In your setter method for the property, there is a simple assignment of your instance variable to the new value, eg:
- (void)setString:(NSString*)newString
{
string = newString;
}
This can cause problems since Objective-C objects use reference counting, and therefore by not retaining the object, there is a chance that the string could be deallocated whilst you are still using it.
retain: this retains the new value in your setter method. For example:
- (void)setString:(NSString*)newString
{
[newString retain];
[string release];
string = newString;
}
This is safer, since you explicitly state that you want to maintain a reference of the object, and you must release it before it will be deallocated.
copy: this makes a copy of the string in your setter method:
- (void)setString:(NSString*)newString
{
if(string!=newString)
{
[string release];
string = [newString copy];
}
}
This is often used with strings, since making a copy of the original object ensures that it is not changed whilst you are using it.
Cocoa uses reference counting to manage memory. Objects with a reference count of 0 are deleted.
assign - does nothing to reference count simply points your variable to the data
retain - points your variable to data and adds 1 to reference count, data is guaranteed to be there while your variable is still alive
copy - makes a copy of data, points your variable at it and makes the retain count 1
More detail here, at Apple's own documentation.
assign - the ivar is set by doing a simple assignment. Implementation:
- (void) setFoo:(NSString *)newFoo {
foo = newFoo;
}
retain - the ivar is sent the retain message before doing the assignment. Implementation:
- (void) setFoo:(NSString *)newFoo {
if (foo != newFoo) {
[foo release];
foo = [newFoo retain];
}
}
copy - the ivar is sent the copy message before doing the assignment. Implementation:
- (void) setFoo:(NSString *)newFoo {
if (foo != newFoo) {
[foo release];
foo = [newFoo copy];
}
}