NSString Release - objective-c

I have this code of string and I have problems trying to free up memory, I have understood that only those who release it initializes and is not autorelease but I had problems with the string "end", and as nSum release.
NSString *urlBase = [[NSString alloc] initWithFormat:#"http://service.svc/"];
NSString *op = [[NSString alloc] initWithFormat:#"op1"];
NSString * final = [urlBase stringByAppendingFormat:op];
NSString * nSum = sumTextfield.text;
final = [final stringByAppendingFormat:nSum];
//release
[ urlBase release ];
[ op release ];
//[final release]; error
//[final autorelease]; error
thank for you help.
UPDATE:
- (IBAction)mostrarOpciones {
// code (UP)
}

If you create an object using a method that begins with init, new, copy, or mutableCopy, then you own that object and are responsible for releasing it (or autoreleasing it) when you're done with it. If you create an object using any other method, that object is autoreleased, and you don't need to release it. In that case, you actually need to retain the object if you want to keep it around. Apple has a Memory Management Programming Guide that includes all these rules.
The code you've posted is actually correct. You need to release urlBase and op because you created them using a method beginning with init (initWithFormat: in this case). final and nSum are already autoreleased for you. final was created by a method that doesn't begin with init, new, copy or mutableCopy (in this case, the factory method stringByAppendingFormat:). nSum was returned by a method called text, and you can assume that sumTextField "owns" it or has autoreleased it before returning it to you, and so you're not responsible for releasing it.

you cannot release NSString which you did not allocate. Since your two variables are not allocated, they need not to be released.

Related

the autorelease of an object in a ObjC program

Here we have some examples from About Memory Management
In the first example
- (NSString *) fullName {
NSString *string = [[[NSString alloc] initWithFormat:#"%# %#", self.firstName, self.lastName] autorelease];
return string;
}
In this example is how the above method is called
{
Person *aPerson = [[Person alloc] init];
NSString *name = aPerson.fullName;
[aPerson release];
}
So I assume that the *name is autoreleased after code flow reaches the closing curly braces.
Is that true?
And in general autorelease of an object, depends on the scope and lifetime of the variable which references that object.
Are there any criteria which manage the autorelease pool of objects in a Objective-C program?
Thanks.
Release of an autoreleased object takes place when the autorelease pool which the object has been pushed to by autorelease is released/drained explicitly, provided that the object's retain count at that moment is 0+ (that is, nobody else but the autorelease pool is retaining it).
An object is not getting autoreleased just because it has gone out of scope. In your example we can only say for sure that it won't get released before the closing curly brace, but as H2CO3 said, without the relevant source code we cannot predict when it is actually cleaned up. In Cocoa (Touch) apps, threads with runloops have a loop-level autorelease pool which they drain at the end of each runloop iteration. If your method is called from the runloop (e.g. as part of an event handler callback), autoreleased objects will be released shortly after the handler code returns; otherwise there is no such guarantee.
Note that the above holds for non-ARC environment; others may confirm whether it's still valid or not when using ARC.

Lifetime of weak local variables with ARC

If I have a piece of code that looks like this:
- (void)testSomething
{
__weak NSString *str = [[NSString alloc] initWithFormat:#"%#", [NSDate date]];
NSLog(#"%#", str);
}
the output will be (null) because there are no strong references to str and it will be immediately released after I allocate it. This makes sense and is spelled out in the Transitioning to ARC guide.
If my code looks like this:
- (void)testSomething
{
__weak NSString *str = [NSString stringWithFormat:#"%#", [NSDate date]];
NSLog(#"%#", str);
}
then it correctly prints out the current date. Obviously you would expect it to work in a non-ARC world, since str would be autoreleased and therefore valid until this method exits. However, in ARC-enabled code people generally consider the two forms (stringWithFormat & alloc/initWithFormat) to be equivalent.
So my question is whether code like the second example is guaranteed to work under ARC. That is, if I have a weak reference to an object that I get via what we would normally consider an autoreleasing convenience constructor, is it guaranteed to be safe to use that reference in the same scope I normally would have without ARC (i.e. until the method exits)?
The conventions of autoreleasing and allocing still apply in the world of ARC. The only difference is that ARC will insert extra retain/release calls to make it much harder to leak objects or access a dealloced object.
In this code:
__weak NSString *str = [[NSString alloc] initWithFormat:#"%#", [NSDate date]];
The only place the object is retained (or equivalent) is the alloc. ARC will automatically insert a release command, causing it to be immediately dealloced.
Meanwhile, in this code:
__weak NSString *str = [NSString stringWithFormat:#"%#", [NSDate date]];
By convention, the return value of a convenience constructor like this must be an autoreleased object*. That means the current autoreleasepool has retained the object and will not release it until the pool is drained. You are therefore all but guaranteed that this object will exist for at least the duration of your method - although you probably shouldn't rely on this behaviour.
(* or retained in some other way)
The lifetime of a local weak variable is not guaranteed at all. If the object that the variable points to is deallocated, the weak variable will point to nil afterwards.
If you have a weak reference to an object that you got via a method that does not return a retained object, it is not safe to assume that this object lives until the method exits. If you want to make sure that the object survives, use a strong reference.
Here is an example that shows that a non-retaining method's return value is not guaranteed to end up in the autorelease pool:
Create a new iOS project (Single View App using ARC and Storyboards)
Add this method to the AppDelegate.m:
+ (id)anObject
{
return [[NSObject alloc] init];
}
Replace -application:didFinishLaunchingWithOptions::
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
__weak id x = [AppDelegate anObject];
NSLog(#"%#", x);
return YES;
}
Important: Now set the Optimization level for Debug to -Os.
In this example, +[AppDelegate anObject] acts like a convenience constructor, but you will see (null) logged if you execute it on a device with -Os optimization. The reason for that is a nifty ARC optimization that prevents the overhead of adding the object to the autorelease pool.
You may have noticed that I switched to not using a library method like +[NSString stringWithFormat:]. These seem to always put objects in the autorelease pool, that may be for compatibility reasons.

Returning autoreleased objects using ARC

Assuming that I wrote the code below in a class A:
-(NSArray *) returnListNames {
NSArray *returnList = [NSArray arrayWithArray:myListNames];
return (returnList);
}
And in a class B I get that list in some scope in this way:
{
/* Without ARC I would retain the array returned from ClassA
to guarantee its reference like this:
[[myClassA returnListNames] retain]; */
NSArray *myNames = [myClassA returnListNames];
}
Considering that the returnList was allocated using an autorelease method, how can I guarantee that I won't lose the reference to it using ARC (under which I can't use retain)?
Will I have to use [[NSArray alloc] init] on the myNames array? Or I must use alloc on returnList instead of an autorelease method? Or can I just rely on ARC? Or is there another solution?
ARC will handle this for you, so you can just rely on it and go about your business with that array. If it sees that you need to retain myNames, it will add a retain call for you for example, or do whatever else it actually does when you compile the code that uses it.

Releasing of strings

I got a doubt that when should the strings are released.I am not made any allocation to the string is there any necessary to release the string?
No if you do not "allocate" the string they are auto released.
for example
NSString *aTestString = [NSString stringWithFormat:#"Hello %#",#"World"];
This string is auto released, so you do not have to call [aTestString release];
If you would do:
NSString *aTestString = [[NSString alloc] initWithFormat:#"Hello %#",#"World"];
Then you would need to release it by [aTestString release]; because you manually allocated.
Therefore it is wise to autorelease it, so you do not have to think of it later on
NSString *aTestString = [[[NSString alloc] initWithFormat:#"Hello %#",#"World"] autorelease];
But that would just be the same as the first piece of code I gave ya.
Back to the point, no you do not have to manually release it as long as you do not allocate it yourself.
Did you create the string via a call to alloc, new, or a method containing copy? Did you explicitly retain the string yourself? If you got the NSString from a CFStringRef, did you create the CFStringRef with a function that included create? If not, you don't have to do anything. If you did, you have to either release or autorelease the string.
Object allocation/deallocation rules
You need to call [Object release] if and only if:
You called [Object alloc]
You called [Object retain]
You called [Object new]
If you did not explicitly allocate or retain the object, then you need to release it. If you got the object via a class method, the method did something like this: return [[[Object alloc] init] autorelease];. This allocates a new object, but is autoreleased when the NSAutoReleasePool next gets a chance.

Releasing objects returned by method

Ok, I know the answer to this question should be obvious, but I need a little push in the right direction.
I find myself writing a fair number of methods that follow the following pattern:
-(NSThing*)myMethod{
NSThing *thing = [[NSthing alloc] init];
// do some stuff with the thing
return thing;
}
My question is, how do I handle the release of this object? Clearly I can't release it within the method.
usually you would autorelease it
-(NSThing*)myMethod{
NSThing *thing = [[NSthing alloc] init];
// do some stuff with the thing
return [thing autorelease];
}
Autoreleasing is the easy way to get out of this, as newacct said. However, you should take into consideration the "ownership" of the object you're returning.
In Objective-C, the general rule of thumb is that any method with alloc, new, or copy in its name returns an object that is not autoreleased, while other methods (like class methods) pre-autorelease the object to be returned. So these three are not equivalent in terms of autorelease (although the compiler may do some magic and reduce them all to string constants anyway):
// Autoreleased
NSString *string1 = [NSString stringWithString:#"aString"];
NSString *string2 = [[[NSString alloc] initWithString:#"aString"] autorelease];
// NOT autoreleased
NSString *string3 = [[NSString alloc] initWithString:#"aString"];
Your code can take a similar approach, where you consider who owns the object you're returning. In the specific example you provided, the method is the one allocing and initing the object, so in general you're responsible for autoreleaseing [sic] it within your own method. However, if you were to write a method that takes a preexisting object and modifies it in some way, you would not own that object and would not be responsible for autoreleasing the returned object. (Doing so could actually cause problems down the road when the autorelease pool to which the object belongs gets drained.)
See also (thanks to Peter and Quinn in the comments!):
Memory Management Rules