Retain issue with iOS Blocks - objective-c

Similar things have been asked before, but I was unable to solve my current problem with any of these answers.
Situation:
CustomType *Object;
BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) {
//Calculate Average from Total and Pulse
Total /= Pulse;
[Trigger setValue:Total];
};
Object = [CustomType CreateObject]; //Autoreleased Object
[Object addCallback:^{ return doAverage(Object, 56, 32); }];
[Array addObject:Object]; //Adds to collection.
The issue at hand is a retain cycle as you probably already figured.
Object keeps a reference to the block in addCallback, and the block doAverage retains the reference to Object.
Using an instance variable is out of the question, because I want to reuse the variable Object for multiple objects. (Temporary variable).
Using a local variable results in the retain count.
And using __block CustomType *Object doesn't work either, because for whatever reason Trigger ends up as nil once the callback is actually called.
Any ideas?
I have a makeshift solution, but it seems rather...hacky.

Several things. First, I would like to see your addCallback: method. It's possible that you've implemented it incorrectly. For example, if you store a block for use later, you must copy it. If it's incorrect, all bets are off on the rest of the stuff.
And using __block CustomType *Object doesn't work either, because for
whatever reason Trigger ends up as nil once the callback is actually
called.
So if it's nil, then that means you assigned nil to Object somewhere.

As already stated, this answer is rather hacky and I'd be very happy if someone could point me in a better direction.
Apparently a primitive datatype in combination with a __block variable does the trick, though this is a bit complicated.
void *Ptr; //Variable for Block.
__block CustomType *Obj; //Function variable, mutable by block.
BOOL (^doAverage)(void *, int, int) = ^(void *Trigger, int Total, int Pulse) {
CustomType *T = (CustomType *)Trigger; //Conversion
//Calculate Average from Total and Pulse
Total /= Pulse;
[T setValue:Total];
};
//Convenience method.
CustomObject *(^Add)(CustomObject *) = ^(CustomObject *)NewObject {
[Array addObject:NewObject];
Obj = NewObject; //Assigns to the local block-Variable.
return Obj;
};
Ptr = Add([CustomObject CreateObject]); //Creates the Object, and adds it to the array.
[Obj addCallback:^{ return doAverage(Ptr, 56, 32); }];
Since Ptr is a primitive type, it will NOT be retained and does not have to be released. At the same time, it assumes the address of the Object in question and thereby doubles as it.
Once the object is released, so is the block with the pointer and everything is good.
Once the block is called, the pointer needs to be cast to the type in question, but that's only a minor problem.
Add is optional of course, but I don't like the syntax Ptr = Obj = [CustomObject CreateObject];

CustomType *Object;
BOOL (^doAverage)(CustomType *, int, int) = ^(CustomType *Trigger, int Total, int Pulse) {
//Calculate Average from Total and Pulse
Total /= Pulse;
[Trigger setValue:Total];
};
Object = [CustomType CreateObject]; //Autoreleased Object
[Object addCallback:^{ return doAverage(Object, 56, 32); }];
Taylor said -> "What I want however is a 'non-retained copy of the object' in question, which will be 'lost' once the corresponding object is deallocated."
This code doesn't seem to cause a retain-cyle unless you use copy on or inside of addCallback([^{}copy]);..
Where is it exactly the copy is used in your code? Inside of addCallback? if this is like:
addCallback(o) {
o = [o copy];
o();
then do a [o release]; when you done with a block object.. do not release it in dealloc()
}
if you have never used copy anywhere, nothing to be worried about.. It all happens in the stack that means no retain cyles at all unless it is not a global one!
In case there is a retail-cyle, do not use __block __weak etc instead do release whatever object it is in the end of the block.. and bear in mind that no copy no retain cycle..

If your deployment target is at least iOS 5 (or OS X 10.7), you can use "zeroing weak references":
CustomType *object = [CustomType makeObject];
__weak CustomType *weakObject = object;
[object addCallback:^{
CustomType *strongObject = weakObject;
if (strongObject)
return doAverage(weakObject, 56, 32);
else
return 0;
}];
(I have used a makeObject instead of CreateObject for the name of the "factory method", because methods with "create" in their name are expected to return a (+1) retain count object, not an autoreleased object.)
The __weak reference does not increment the retain count, therefore no retain cycle is created. If the object is destroyed because the last strong reference to it is gone, then weakSelf is set to nil. Inside the block a strong reference is created, which either points to the object, if it still exists, or is nil, if it does not exist anymore.
If I understand you code correctly, the callback will not be called if the object has been released. In that case a __unsafe_unretained reference is sufficient (which works also on iOS 4):
CustomType *object = [CustomType makeObject];
__unsafe_unretained CustomType *unsafeObject = object;
[object addCallback:^{
return doAverage(unsafeObject, 56, 32);
}];

Try declaring the Object as
__weak CustomType *Object

Related

__weak pointer type holding on to the object even after strong pointer releases the same object

After having declared the property as a weak type and then passing it as an argument in the removeObject: message, the "selectedLine" pointer is no longer supposed to hold on to the object that it was previously pointing to.
After this line-
[completeLines removeObject:selectedLine]//completeLines is a mutable array here.
shouldn't the selectedLine pointer be pointing to nil immediately after this using the ARC principle. I already had made it weak type earlier.
Coz a removeObject: implementation must look something like this:
-(void)removeObject:(id)obj{//obj pointer now shares an object with (__weak)selectedLine pointer
__weak id ptr;
for (ptr in completeLines)
{
if(ptr==obj)
obj=nil;// releasing a strong reference makes ptr as well as selectedLine automatically release the particular Line object.
}
}
But when I'm logging it to the console, the weak pointer still appears to hold to the object:-
NSLog(#"%#", selectedLine);
In the console I see the details of the object when i should be seeing (null) instead, logged to the console.
Pls anyone explain why is this the case..
It's not working because under ARC when you add weak reference to an array it holds reference of this object. If you want to weak reference inside array you should wrap this reference in a block. Like this:
typedef id (^WeakBlock)(void);
array = [NSMutableArray array];
obj = [NSObject new];
WeakBlock block = ^(void) {
typeof(obj) __weak wObj = obj;
return wObj;
};
[array addObject:block];
WeakBlock blockInArray = [array firstObject];
NSLog(#"%#", blockInArray());
obj = nil;
NSLog(#"%#", blockInArray());
Output:
2014-06-28 11:25:56.174 weak-array[18604:60b] <NSObject: 0x8c7fcb0>
2014-06-28 11:25:56.175 weak-array[18604:60b] (null)

ARC __block behavior equivalent in MRC?

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.

How to choose the ARC bridge specifier for object pointer pointers (id *)?

I wrote a little convenience method on NSArray which works like PHP's list() function for "unpacking" an array into distinct objects:
- (void)unpackInto:(__strong id *)obj1, ...
{
__strong id *idPtr;
va_list args;
va_start(args, obj1);
idPtr = obj1;
NSUInteger idx = 0;
NSUInteger count = [self count];
while (idPtr != NULL && idx < count) {
*idPtr = [self objectAtIndex:idx];
// Increment the args and idx count
idx++;
idPtr = va_arg(args, __strong id *);
}
}
I originally had __autoreleasing id * but ran into a EXC_BAD_ACCESS issue when this method was called (twice actually, if it matters) on a thread with it's own autorelease pool to unpack the contents into temporary local stack vars. When the main thread came around and attempted to autorelease the contents (again), EXC_BAD_ACCESS was thrown.
Can anyone help me follow the logic with these bridging parameters in this case? I'm concerned that __strong will lead to the slightly less obvious but equally evil twin cousin: memory leak...
I haven't seen your source code, but answer to most ARC problems can be solved if you think in terms of ownerships than retain/release/auto-release pools. Try to answer, who owns the array and who owns the unpacked pointers. If I understand you correctly, your calling method looks something like this
NSArray *arr = [NSArray arrayWithObjects:#"a", #"b", #"c", #"d", nil];
NSString *a, *b, *c, *d;
[arr unpackInto:&a, &b, &c, &d, nil];
Is your array deallocated before you access the unpacked variables? Remember that __autoreleasing doesn't "retain" the values onto your variable argument pointers. So if your array is deallocated, your pointers become garbage.
My guess, your EXC_BAD_ACCESS is because, your main array gets deallocated.
__strong shouldn't be used when you return by reference. It will not increase the retain count. There is no way to let ARC know that, these variables are to be released in the calling method. So ARC releases them after its scope. The only way to pass an allocated object to a calling method and let the calling method deallocate, is by returning it from a method that belongs to a init- family. When you return values across method boundaries, ARC uses method family (or the macros NS_RETURNS_RETAINED/NS_RETURNS_NON-RETAINED) to determine who "owns" the pointer.
You can use __strong for passing by reference if you pass a const pointer (non-writeback pointers) In fact, for const pointers without ownership qualifiers, __strong is implied.
More on this on LLVM documentation here
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.restrictions.pass_by_writeback

What does Objective-C actually do when you declare an object?

I have read the memory management guide from Apple and I don't see where this case is explained...
Many times, especially when writing a class method to return an instance of a class, I'll start it out like this, because that's how I've seen it done, and it works.
[NOTE] This code is from memory - I'll update it when I get home to show an example that really works (I made this up to illustrate it, but obviously I don't recall it well enough to construct something that makes sense...
[EDIT] Here's my actual method - of course everyone was right that I must be calling alloc which I am.
+ (id)player
{
Player *player = nil;
if ((player = [[[super alloc] initWithFile:#"rocket.png"] autorelease])) {
[player setProjectileType:kProjectileBullet];
[player setProjectileLevel:1];
[player setInvincible:YES];
[player setEmitter:[CCParticleSystemQuad particleWithFile:#"exhaust.plist"]];
[[player emitter] setPosition:ccp(0.0, player.contentSize.height/2)];
[player addChild:player.emitter];
}
return player;
}
So what I got from the responses is:
* Declaring the instance just gets me a pointer to a memory location and tells Xcode what class the object will be.
* Setting the pointer to nil pretty much just sets it to zero - keeping it from having garbage in it (right?)
* Since I'm autoreleasing the instance, the object that is returned is also autoreleased.
Thanks for helping me understand this!
Can someone explain what the compiler does when it sees this?
DooDad* aDooDad = nil;
If you are really interested in what the compiler does, the answer is: the compiler will reserve some memory on the stack for the local variable aDooDad, which is a pointer type (it is generally 64 or 32 bits in size depending on the processor). That pointer is then initialized to contain nil (usually 0x00..00).
A statement like this:
DooDad* aDooDad = [[DooDad alloc] init...];
makes use of pointer variable aDooDad to store the address in memory of the object that is further allocated (which is the address of memory reserved by alloc).
So, in the end,
DooDad* aDooDad = nil;
is not declaring an object, just a variable whose content is interpreted as the address of an object of DooDad type. Such declaration, therefore, is just like any other declaration you know, e.g. when initializing an int to 0, so that later you can assign it some value in an if statement.
A statement like:
[aDooDad doSomething];
is interpreted by the Objective-C runtime system like: send message doSomething to the object whose address is stored in aDooDad. If that address is nil no message is sent. On the other hand, if you dereference a nil pointer: *aDooDad you'll get undefined behavior.
Pointers are pretty low level stuff. I hope this helps.
If you're familiar with C or C++, variables can be created in one of two ways, statically on the call stack, or dynamically on the heap. Variable memory created on the stack is is reclaimed when the current stack frame goes out of scope, so you never need to worry about creating or destroying it. In Objective-C, objects are always dynamically created. Primitives (like int, float, pointers, etc), can either be statically or dynamically created. For illustration:
- (id)something {
NSObject myObject; // Illegal static object allocation
NSObject* myObject; // Legal primitive (pointer) static allocation
int myInt; // Legal primitive static allocation
int* myIntPtr; // Legal primitive (pointer) static allocation
}
So when you say DooDad* dodad = nil;, you're creating a primitive (pointer to a DooDad) on the stack. Being a stack variable, you don't alloc or dealloc it, just like you wouldn't worry about alloc'ing or dealloc'ing any of the memory in the following method:
- (id)allStackVariables {
int myInt = 0;
float myFloat = 0.0f;
float* myFloatPtr = NULL;
NSObject* myObject = nil;
}
Setting it to nil simply sets the contents of the variable to whatever the compiler defines to be nil, something like 0x000000 in hex. Saying DooDad* dooDad = nil; is conceptually identical to saying something like int myInt = 0;
Declaring simple gives you a pointer you can use later. No memory is allocated.
Not sure what the intent of the method you posted, but it seems wrong on many levels. It will return nil, always. Unless it's an initializer method, it should not call [self init]. If it is an initializer method, it should return self and be named something like "init..."

What does #property(retain) do?

What does #propert(retain) do? it doesn't actually retain my object by my tests:
id obj = getObjectSomehow();
NSLog(#"%d", [obj retainCount]);
propertyWithRetain = obj;
NSLog(#"%d", [obj retainCount]);
// output:
// 1
// 1
How can I make a property that will really retain the object?
You're not using your property there, that's why it's not retaining!
Try this :
id obj = getObjectSomehow();
NSLog(#"%d", [obj retainCount]);
self.propertyWithRetain = obj; // Note the self. :)
NSLog(#"%d", [obj retainCount]);
Using self. will use the property. Just using the variable name won't.
EDIT especially for #bbum (who raises a very fair point in the comments)
Don't rely on using retainCount - you don't know what else has retained your object and you don't know if some of those retains are actually scheduled autoreleases so it's usually a misleading number :)
propertyWithRetain = obj;
That just sets the ivar backing the property directly. When an #property is synthesized, if there is no instance variable declared, then one is generated automatically. The above is using that ivar directly.
self.propertyWithRetain = obj;
That would actually go through the #synthesized setter and bump the retain count.
Which is also why many of us use #synthesize propertyWithRetain = propertyWithRetain_; to cause the iVar to be named differently.
Note that, even in this, calling retainCount can be horribly misleading. Try it with [NSNumber numberWithInt: 2]; or a constant string. Really, don't call retainCount. Not ever.