Jakob Bjerre Jensen
Jakob Bjerre Jensen

Reputation: 429

How to release an object owned by another object in Objective C

In Objective C how do I explicitly release an object owned by another object? Or perhaps equivalently inform the owning object that it does not own the child object anymore. Consider the following:

- (void) testWithNSString:(NSString *)val
{
  NSData *data = [val dataUsingEncoding:NSASCIIStringEncoding];
  // ...
  // now I want to explicitly release data e.g. due to low memory
}

In [val dataUsingEncoding:NSASCIIStringEncoding] an NSData object is returned and I assume (due to general conventions of ownership) that it will be released, when val is released. This seems acceptable from a non-leaking perspective. But this strategy raises two issues:

  1. What if I want to explicitly release data object immediately e.g. due to low memory?
  2. What if I do not want the caller of testWithNSString to be left with an NSString val object (after the testWithNSString has returned), which suddently has ownership of new objects?

Upvotes: 0

Views: 158

Answers (3)

sergio
sergio

Reputation: 69027

In [val dataUsingEncoding:NSASCIIStringEncoding] an NSData object is returned and I assume (due to general conventions of ownership) that it will be released, when val is released

This is incorrect. dataUsingEncoding will create a new NSData object that has no relationship with val (as to lifetime). It is an autoreleased object and it will be released at the next cycle of the run loop (approx, we don't know exactly), unless you retain it somehow.

What if I want to explicitly release data object immediately e.g. due to low memory?

If you want the object to be released immediately, and you are using ARC, you can simply assign nil to its pointer:

data = nil;

If you are not using ARC, your best option is to wait for the run loop autorelease pool to do its job. Or you can create a local autorelease pool in your method, so that autoreleased objects are drained at the end of the method and not at the next run loop cycle. This will make a difference only in case of long-running methods (or chain of methods), so I don't know if it would make sense in your case.

What if I do not want the caller of testWithNSString to be left with an NSString val object (after the testWithNSString has returned), which suddently has ownership of new objects?

As I said, val has no ownership of data.

Summing this all up, your data object is autoreleased and it will be pretty soon after your method ends (unless it is a long-running method); so data memory will be recovered in an efficient way and I would not worry about it (unless it is a long-running method, as I said).

Upvotes: 1

DrummerB
DrummerB

Reputation: 40211

First of all, you should never ever release an object that you don't own. The returned NSData object will not be released when val is released. The two objects are completely independent (except that data originated from val).

dataUsingEncoding: returns an autoreleased object. That means data will be released at the end of the run loop.

If you are afraid that you will run low on memory and want it to release earlier you can use an NSAutoreleasePool pool:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSData *data = [val dataUsingEncoding:NSASCIIStringEncoding];
// do something with data.
[pool release];

This will release data when you release the pool.

Upvotes: 2

Karl Monaghan
Karl Monaghan

Reputation: 910

Assuming you're using ARC, setting val to nil should release it.

Upvotes: -1

Related Questions