NSString assignment, release required? - objective-c

If I have a property in my class like so:\
#interface Test
NSString *str;
#end
And in my init in the .m:
str = #"Test";
Do I need to manually release that in the classes dealloc?
What about this kind?
NSString *myStr = [NSString stringWithFormat:#"%#", someString];
Do I need to release that too?

You should really just use ARC, but to answer your specific question, no: you don't need to release those. You only release what you "own", and you only own things you got from a method that contains one of [new, alloc, retain, copy].
That said, since you don't own those strings, you should retain (or copy) them if you need them to stick around.

You shouldn't have to release if you are using ARC in your project (Automatic Reference Counting). ARC is enabled for iOS 5+ so if you are targeting iOS 5 or higher, you dont have to release anything.

If you're not sure if you're using ARC or not, just try to release/retain. If it shows a warning saying you can't release/retain, ARC is enabled, else is disabled and you'll have to retain & release.

Both constructs1 create autoreleased strings. You need to retain them (explicitly or by assigning to a retained property), otherwise you will end up with dangling references once the autorelease is called2. Once you call a retain on an object, releasing it becomes your responsibility.
A more robust approach with NSStrings is to use copy properties, rather than retaining them. Doing so lets you avoid issues when a NSMutableString passed into your init method gets mutated after you have validated its content.
1 I am assuming that you are asking about pre-ARC version of Objective C tools; otherwise, you will not be able to call retain or release explicitly.
2 This usually happens some time after you exit from the method, and the control passes back to the run loop.

Related

Can I send release to an ivar without alloc/init?

I have an NSString property:
.h file
#property (nonatomic, retain) NSString *str;
.m file
#synthesize str;
What is the retain count of str without alloc/init? Can I [str release] in a method?
I am assuming your new to the concept of memory management, so I would advise to have a read of the apple docs around memory management before you continue with your development.
Basic Memory Management Rules
You own any object you create.
You can take ownership of an object using retain.
When you no longer need it, you must relinquish ownership of an object you own.
You must not relinquish ownership of an object you don't own.
I will refer you to the Memory Management Policy in the apple docs for a good understanding of memory management
So when you have read the apple docs you will fully understand what is going on in your code, but if you don't this is what is wrong. You can not release an object that you don't have ownership of. This violates point 4 of the Basic memory management rules in the apple docs. To take ownership of this object you must do str = [[NSString alloc] init]; (This is not needed with ARC) in your .m file.
My recommendation though would be to read up about ARC it is a lot better then handling the memory management yourself. As you would no longer have to do things such as [str release]; once you wanted to relinquish ownership of the object as it is done automatically.
You cannot release an object that has not yet been allocated.
Use ARC where possible, and read about changes to Objective-C in the past 2 years: it is no longer necessary to synthesize variables declared in .h in your .m
You shoudn't release an object that has not yet been allocated. But if you do it it means you are sending a message to a nil object. That is safe because a message to nil does nothing and returns nil, Nil, NULL, 0, or 0.0.
Yes you can release this object. Whenever you send alloc, copy, new, retain any of these message to an object. It's retain count increased by 1. And you become the owner of that object. So you must release the object to relinquish the ownership.
And when you use ARC the compiler do it for you. Hope it helps.
As its a retained property you can do self.str=nil; instead of [str release] safely.
You can not do [str release] as we can release only what we alloc and init by ourself and its not init yet.

About retain/release for properties

I have this in my .h file:
#property (nonatomic,retain) CCTexture2D *tempScreenshot;
Since it says "retain", I'm assuming that whatever value is stored in tempScreenshot is retained.
Do I have to release tempScreenshot in the dealloc method of my class?
Also, if I use the set method to give a new value to tempScreenshot, this new value will be retained, right? What happens to the old value?
Since you're saying "retain" I am assuming this is manual memory management code. If at all possible, you should switch to automatic reference counting (ARC). It dramatically simplifies this work and is faster than the equivalent manual code. Other than support for older OSes, there is almost never a reason to do manual memory management anymore.
Since it says "retain", I'm assuming that whatever value is stored in tempScreenshot is retained.
Whenever you call [self setTempScreenshot:], the accessor will retain the parameter and release the old value. Assigning the ivar directly will not give you any of this. You should always use the accessor except in init and dealloc.
Do I have to release tempScreenshot in the dealloc method of my class?
Yes.
Also, if I use the set method to give a new value to tempScreenshot, this new value will be retained, right? What happens to the old value?
It will be released as long as you use the accessor.
The retain keyword marks the property as retain upon assignment, meaning that on a set, retain will be called on the new value, and release will be called on the old value.
You will need to release the object on dealloc.
In your dealloc method, do: self.tempScreenshot = nil;
This will cause the object to be released. It will then be deallocated assuming nothing else has retained it.
If you were to write your own setter method to retain an object it would look like this.
//Assume an instance variabled name obj for this example
- (void)setAndRetainObjectExample:(NSObject *)newObj {
[obj release];
obj = newObj;
[obj retain];
}
Using the synthesized methods is much cleaner, but looking at it this way may clear up any confusion.

ARC, non-ARC, and inheritance

I haven't used ARC yet other than to deal with it when it forces it's way into a project via 3rd party code. I've read all the ARC docs but haven't seen an answer to this question:
If I have a class that's defined in a module compiled with -fobjc-arc, can I derive a new class from this in a module that is NOT ARC-enabled?
In my mind it should work fine as long as the derived class doesn't attempt to touch any ivars in the root class. It seems to me that even having a dealloc method that calls [super dealloc] would be fine in the derived class.
And, what about the other way around? Can I derive a ARC-enabled class from a non-ARC class? Should work fine too, right?
Bonus points: are there any gotcha's when mixing ARC and non-ARC code that I should make myself aware of?
There are no issues that I am aware of. You have to realize that ARC is something like a source code preprocessor, adding the memory management calls for you during the compilation. When you arrive at the linking phase, you can’t really tell ARC code from non-ARC code. (This is probably an over-simplification, but one that should work for your purposes.) If your derived class has correct memory management and the super class has correct memory management, the result will work fine.
About the only difference I can think of is handling of weak properties. But I don’t know enough about those to say if it’s possible to arrive at buggy code using some combination of ARC and MRC code with weak properties.
This was a comment, but having thought about it I want to expand what it said.
Have you tried inheriting an ARC class from a normal subclass? My thoughts (without having tried it either) is that this will not work. Firstly, if the ARC class has public properties or ivars using ARC keywords, like weak I think you will get errors during compilation from the header file. Secondly, I don't know how the dealloc would work. Do you need to call [super dealloc] or not? I don't know.
Anyway, if your superclass is ARC, why would you not use ARC in any subclasses? There's no advantage to doing that at all.
Can I derive a ARC-enabled class from a non-ARC class? Should work fine too, right?
I was going to say that won't work either, but I would have been wrong. Virtually everything has to inherit from NSObject which is manual reference counted.
Yes, you may both implement non-ARC ancestor from ARC parent class, and ARC ancestor from non-ARC parent class.
Actually, ARC is a syntax sugar, or you may say, is just preprocessor which analyzes your source code at compile step and inserts appropriate [release] and [retain] calls to your code. At runtime level nothing is changed (except for the weak properties).
ARC means the compiler takes care of memory management, non-ARC means you take care of it, but in both cases memory management works exactly the same way:
If an object must stay alive, its retain counter is increased (that's what retain does)
If an object is not needed anymore, its retain counter is decreased before the reference to it is lost (that's what release does)
If you are done with an object but it must not die yet, e.g. as you need to return it as a method result (and you don't want to return a dead object), it must be added to an autorelease pool that will decrease its retain count at a later time (that's what autorelease does, it's like saying "call release on that object at some future time.")
Newly created objects have a retain count of 1.
If the retain count reaches zero, the object is freed.
Whether you do all that yourself or the compiler does it for you, it plays no role. After compilation, these methods are being called, also with ARC, but with ARC the compiler has decided for you when which method is called. There is some extra magic, e.g. ARC doesn't always have to add objects to autorelease pools when returning them as method result, this can often be optimized away, but you don't have to care as this magic is only applied if the caller and the called method both are using ARC; if one of them isn't, then a normal autorelease is used (which still works in ARC exactly as it used to).
The only thing you must take care of is retain cycles. Whether you use ARC or not, reference counting can't deal with retain cycles. No difference here.
Pitfalls? Careful with Toll Free Bridging. A NSString * and a CFStringRef are in fact the same thing but ARC doesn't know about the CF-world, so while ARC takes care of the NSString, you must take care of the CFString. When using ARC, you need to tell ARC how to bridge.
CFStringRef cfstr = ...;
NSString * nsstr = (__bridge_transfer NSString *)cfstr;
// NSString * nsstr = [(NSString *)cfstr autorelease];
Code above means "ARC, please take ownership of that CFString object and take care of releasing it as soon as you are done with it". The code behaves like the code shown in the comment below; so careful, cfstr should have a retain count of at least one and ARC will release it at least once, just not yet. The other way round:
NSString * nsstr = ...;
CFStringRef cfstr = (__bridge_retained CFStringRef)cftr;
// CFStringRef cfstr = (CFStringRef)[nsstr retain];
Code above means "ARC, please give me ownership of that NSString, I'll take care of releasing it once I'm done with it". Of course, you must keep that promise! At some time you will have to call CFRelease(cfstr) otherwise you will leak memory.
Finally there's (__bridge ...) which is just a type cast, no ownership is transferred. This kind of cast is dangerous as it can create dangling pointers if you try to keep the cast result around. Usually you use it when just feeding an ARC object to a function expecting a CF-object as ARC will for sure keep the object alive till the function returns, e.g. this is always safe:
doSomethingWithString((__bridge CFStringRef)nsstr);
Even if ARC was allowed to release nsstr at any time as no code below that line ever accesses it anymore, it will certainly not release it before this function has returned and function arguments are by definition only guaranteed to stay alive until the function returns (in case the function wants to keep the string alive, it must retain it and then ARC won't deallocate it after releasing it as the retain count won't become zero).
The thing most people seem to struggle with is passing ARC objects as void * context, as you sometimes have to with older API, yet that is in fact dead simple:
- (void)doIt {
NSDictionary myCallbackContext = ...;
[obj doSomethingWithCallbackSelector:#selector(iAmDone:)
context:(__bridge_retained void *)myCallbackContext
];
// Bridge cast above makes sure that ARC won't kill
// myCallbackContext prior to returning from this method.
// Think of:
// [obj doSomethingWithCallbackSelector:#selector(iAmDone:)
// context:(void *)[myCallbackContext retain]
// ];
}
// ...
- (void)iAmDone:(void *)context {
NSDictionary * contextDict = (__bridge_transfer NSDictionary *)context;
// Use contextDict as you you like, ARC will release it
// prior to returning from this method. Think of:
// NSDictionary * contextDict = [(NSDictionary *)context autorelease];
}
And I have to real big gotcha for you that are not that obvious at first sight. Please consider this code:
#implementation SomeObject {
id _someIVAR;
}
- (void)someMethod {
id someValue = ...;
_someIVAR = someValue;
}
This code is not the same in ARC and non ARC. In ARC all variables are strong by default, so in ARC this code behaves just like this code would have:
#interface SomeObject
#property (retain,nonatomic) id someIVAR;
#end
#implementation SomeObject
- (void)someMethod {
id someValue = ...;
self.someIVAR = someValue;
}
Assigning someValue will retain it, the object stays alive! In non-ARC the code will behave like this one:
#interface SomeObject
#property (assign,nonatomic) id someIVAR;
#end
#implementation SomeObject
- (void)someMethod {
id someValue = ...;
self.someIVAR = someValue;
}
Note the property is different, as ivar's in non-ARC are neither strong or weak, they are nothing, they are just pointers (in ARC that is called __unsafe_unretained and the keyword here is unsafe).
So if you have code that uses ivars directly and doesn't use properties with setters/getters to access them, then switching from non-ARC to ARC can cause retain cycles in code that used to have sane memory management. On the other hand, moving from ARC to non-ARC, code like that can cause dangling pointers (pointers to former objects but since the object has already died, these point to nowhere and using them has unpredictable results), as objects that used to be kept alive before may now die unexpectedly.

Does stringWithFormat create a retain +1 instance?

I'm declaring an ivar of type NSString on a class. To initialize the value of this ivar I use the following code:
NSString *myVar;
-(void)inAnyMethod
{
myVar = [NSString stringWithFormat:#"%#",theValue];
}
Do I have to release this ivar? According to my understanding, it is not my responsibility. But in most cases, strings that I use in this manner cause leaks.
What am I missing?
You do not have to release it, because that is a convenience method that returns an autoreleased object.
The way to know if you are getting something with a retain count of 1 that you will need to release is using the Cocoa naming conventions which say that anything that starts with new, alloc or contains copy in the method name will return a retain 1 object, the others will return autoreleased objects like in this case.
In addition to Oscar Gomez answer, note that when you use class methods (those methods with plus sign that you can find in the documentation and are not included in Oscar Gomez list, e.g. stringWithFormat is one of them), you have not to worry about memory management. If you create your own class method, you should do the same: return an autorelease object.
Regarding your code, it cannot work if you simply assign your ivar to the NSString object (returned from that method). In fact, at some point of your application cycle, the object will be released (it has been put in a pool) and your ivar will not reference any object anymore.
The trick: create a #property with a copy policy or send a copy message like the following:
myVar = [[NSString stringWithFormat:#"%#",theValue] copy];
Copy is normally used when a class has subclasses of mutable type. Otherwise use retain. Once done, you have the possession for that object and you have to remember to release it. If you don't do it you cause a leak.
[myVar release];
P.S. Since Xcode 4.2 there is a new compiler feature called ARC.
Hope it helps.

Objective-C / Cocoa creation release order?

I am just curious if the order expressed for the release of objects should reflect the reverse of their order in the hierarchy:
// Psuedo code
alloc OBJ_001;
alloc OBJ_001 > OBJ_002;
alloc OBJ_001 > OBJ_002 > NSSting;
release NSString;
release OBJ_002;
release OBJ_001;
I am pretty sure it should (makes sense to me), but have not seen any mention of this in my learning so far.
Gary
It doesn't matter. I assume you mean that OBJ_001 owns OBJ_002 owns the NSString instance, and you own all three objects (co-owning the NSString with OBJ_002 and co-owning OBJ_002 with OBJ_001).
Doing it in reverse order:
Release NSString instance: Nothing happens, because OBJ_002 still owns it.
Release OBJ_002: Nothing happens, because OBJ_001 still owns it.
Release OBJ_001: It releases OBJ_002, which releases the NSString. All three dealloc.
Doing it in the same order:
Release OBJ_001: It releases OBJ_002, then deallocks. OBJ_002 still exists because you still own it.
Release OBJ_002: It releases the NSString, then deallocks. The NSString still exists because you still own it.
Release NSString instance: It deallocks.
Either way, all three instances dealloc. There is no difference.
I prefer the reverse order, but that's purely a style choice.
I wouldn't say so, as long as you're done using it you can release it whenever you want.