0

Should I generally always retain or copy a string value returned from a function?

Consider the following examples:

- (NSString*) getString:
{
    return [[NSString alloc] autorelease];   
}

- (NSString*) getStringAlloc:   // Not sure if this convention is correct 
{
    return [NSString alloc];   
}  

...

In the calling method

NSString* myString = [self getString];

If I want to go on and use myString in the function without it getting released how do I handle it. Also is the name of the second method using the correct conventions.

If I knew the returning string was autoreleasing (from the method name) and it wasn't being changed then presumably the only reason to retain or copy would be so someone didn't change the code in the future. If I didn't mind the value changing then, again I presumably don't need to retain or copy.

Assuming I am not using ARC.

rogermushroom
  • 5,486
  • 4
  • 42
  • 68

4 Answers4

3

No! The scope in which an object is created (your method "getString" in that case) is also responsible for releasing it! So the first approach is the only valid approach.

Also getter-methods are NOT prefixed with "get" by convention. So the method should be called - (NSString*) string instead.

calimarkus
  • 9,955
  • 2
  • 28
  • 48
  • Here's a good article about the ARC feature jaydee3 is referring to: http://longweekendmobile.com/2011/09/07/objc-automatic-reference-counting-in-xcode-explained/ – allaire Mar 05 '12 at 16:42
  • But if I wanted to make sure it didn't change then I would have to retain or copy? Also does that mean the autorelease will sort everything out even once that function has been called and finished? – rogermushroom Mar 05 '12 at 16:44
  • `autorelease` will just send `release` one time to the object, as soon as the end of the current scope is reached. (in your case the end of the calling method.) – calimarkus Mar 05 '12 at 16:46
  • if you need the object for longer, store it in a member variable and retain it. You can use properties for that, so it will be retained automatically. – calimarkus Mar 05 '12 at 16:47
  • @jaydee3 So I should make `MyString` a member variable even if I am only using it in that method? – rogermushroom Mar 05 '12 at 16:51
  • no just use it! it will be still there, if it is autorelease. it will be there until the end of your method. – calimarkus Mar 05 '12 at 16:56
  • And if I return it from that method, I understand from the documentation I can generally rely on it not being released is this correct? – rogermushroom Mar 05 '12 at 17:13
  • Yes you can rely on that. This is how obj-c works. If you want to know more read about AutoreleasePools. https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html – calimarkus Mar 05 '12 at 17:20
1

Your conventions are C++, but if you're going to use Cocoa, you might just as well be all Cocoa. The usage of init, get, set as the prefix of methods have particular meaning in Objective C, so knowing them is important.

Basically, if you create an NSString, it will either be already retained (i.e. you create it with an init function) or autoreleases (i.e. you create it with a method that does not have init or copy in the name). If it's autoreleased, you can use it in the function until the end of the function, and then it will be released sometime in the future. If it's retained, you must release it. ARC will manage this for you, but you still need to know the basics of iOS memory management in order to be successful. You really need to read:

Apple Memory Mangement Guide

Owen Hartnett
  • 5,925
  • 2
  • 19
  • 35
  • Is that, I can use it in the calling function, in my case the function containing `NSString* myString = [self getString];`? – rogermushroom Mar 05 '12 at 16:53
  • Your getString method is bad. You are allocating an NSString *, but you're not calling init, so it won't be a valid string. NSString has instance methods (which begin with a hyphen, and class methods, which begin with a plus. The class methods usually return autoreleased strings. See Azamsharp's example above. – Owen Hartnett Mar 05 '12 at 20:01
1

If you use auto-release, your string won't be released until "the innermost nested autorelease pool will be drained". If you ever created an autorelease pool, you most likely wouldn't read this, so let's suppose that we have the autorelease pools of the system. It will drain them (i.e. delete your objects marked for autorelease) once in a while, when it does not have anything else to do, but always at the end of an event cycle. It means that if you assign your autorelease object to a local variable, you can be sure that it will be kept through the whole scope of your local variable. You should pay attention however when you assign the autorelease variable to a class member, in this case it can be deleted until you next time access it. The best way to avoid this is to use retain type properties.

MrTJ
  • 13,064
  • 4
  • 41
  • 63
  • So I can assume that `MyString` will be around until then end of the function containing the assignment, `(NSString* myString = [self getString];)` – rogermushroom Mar 05 '12 at 16:57
  • Exactly. But don't use "get..." :P – MrTJ Mar 05 '12 at 17:07
  • And if I return it from that method, I understand from the documentation I can generally rely on it not being released is this correct? – rogermushroom Mar 05 '12 at 17:13
  • The short answer is yes. The longer answer is that it will be not released until you are in the same "event loop" (unless you defined your own autorelease pool). Look for the definition if "iPhone event loop" if you're more interested, for example here: http://stackoverflow.com/questions/5402147/what-is-event-loop-in-ios-life-cycle-and-what-is-its-usage-and-what-it-does (the link in the post is also nice stuff to read) – MrTJ Mar 06 '12 at 08:28
1

First of all if you can you should use ARC. ARC takes most of the memory management away from the developer. I said most and not all because if you are using the Core Graphics framework you have to release the object yourself.

You should also consider using the autorelease overload for the NSString object like below:

NSString *someString = [NSString stringWithFormat:@"Hello World"];

The NSString stringWithFormat method will return an autoreleased object.

azamsharp
  • 19,710
  • 36
  • 144
  • 222