3
- (NSString *)allocString{
    NSString *str = [[NSString alloc] init];
    return str;
}

- (void)viewDidLoad{
    NSString *name = [self allocString];

    [name release]; // Can I release an object here?
}

Hi, I just wrote a simple example using NSString. In my real program, instead of NSString, I used a custom UIView class.

allocString creates one NSString instance and its retain count is 1. Without autoreleasing, it just returns an instance.

In viewDidLoad method, a variable "name" just points to an object returned by allocString method, so an instance's retain count is still 1.

Thus, [name release] decreases its retain count.

Is this right? Or do I have to autorelease it in allocString method? Thank you!

pnmn
  • 1,127
  • 1
  • 14
  • 22

3 Answers3

6

What you have done will work. You can retain and release objects from any scope you choose, so long as it all evens out (and the object is deallocated when it is no longer needed by any other object).

But what you are doing is not conventional. If you want to allow the object to live on past the life of a method (so that you can return it and have it picked up by the method caller) then you should use autorelease.

In your example, the first method should probably not retain ownership of the string. It should release it and let the caller pick it up. But, of course, if you release it in the method it will be instantly deallocated. So instead you can autorelease it. By autoreleasing it, your first method is saying "I no longer need this object and relinquish my ownership, but please keep it in memory a little while longer so my caller can retain it if it needs to".

Here's an example:

- (NSString *)createString {
    /* Create a string. This method owns it. */
    NSString *str = [[NSString alloc] init];

    /* Autorelease it. This method does not own it, but wants it to stay in memory temporarily. */
    [str autorelease]

    /* Return it. It will stay in memory till the end of the current run loop */
    return str;
}

- (void)viewDidLoad{
    NSString *name = [self createString];
    /* We now have a copy of the string. Nobody owns it. */
    /* It is due to be released at the end of the current run loop. */

    /* If we want to take ownership of it and prevent deallocation, we should retain it. */
    [name retain];
}

This behaviour is used all throughout the Cocoa APIs. When you see class methods that return a new object, that object will be autoreleased. For example, when you call [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil] you are asking the NSArray class to create an array for you. If exists outside of the arrayWithObjects: method thanks to its autoreleased status. If you do not retain it, it will be released at the end of the current run loop.

Simon Cave
  • 3,971
  • 4
  • 24
  • 28
  • 1
    His first method name begins with "alloc" - by convention, it's supposed to return an object that the caller owns. – Sherm Pendley Mar 29 '11 at 05:05
  • Then, why we do not retain new array instance after this: NSArray *a = [NSArray arrayWithObjects:@"111", @"222", nil]; ? (like this: [a retain];) – Almas Adilbek Mar 04 '12 at 17:19
1

If you just replace "allocString" method name to "newString", it works fine. There's a convention in objective C to handle such methods. That convention is that the method name should start with "new*" and it will not throw any memory leak.

Satyam
  • 15,493
  • 31
  • 131
  • 244
0

Yes, everything you have there will work just fine.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • you are wrong. try creating similar code and in XCode "Build & Analyze", it will show you two memory leaks. – Satyam Mar 29 '11 at 05:19
  • @Satyam: Why is he wrong? The string is alloc'd once, and released once. That's fine, though it is more conventional for the allocString method to autorelease. – Vagrant Mar 29 '11 at 06:07
  • You might have noticed the memory leaks when you "Build & Analyse". If you see the objective C conventions, your answer is correct if the method name starts with "new". But the method name is not starting and so it will lead to leaks. Though both will give you two pointers, either use method starting with "new" or you have to auto release it in allocString method. – Satyam Mar 29 '11 at 07:12
  • @Satyam - there *is* no memory leak. That's a false positive from the analyzer. I'll agree with you that the OP's code isn't conventional, but there certainly aren't any bugs in it. – Carl Norum Mar 29 '11 at 17:22