Usage of NSMutableString vs NSString? - iphone

I am confused between NSString and NSMutable string usage.
Suppose I have instance variables one and two declared in class like this:
NSString *one;
NSMutableString *two;
let us suppose I have created setters and getters of them using properties.
lets say I have changed my "two" string like these:
1. [two appendString:#"more string"];
2. two = #"string"
3. self.two = #"string"
Questions:
would 1st line release previous string and allocate new object and assign value to it.
if yes, then does that mean creating getters and setters are unnecessary in this case ? OR its unnecessary to create properties in NSMutablestring
In this case would the previous allocated string object released ?
Its for sure that first object would be released as we are calling setters here. is this code necessary or we can just use the code line 2 to assign string.
Now about NSString:
As can modify the string like this also :
one = [one stringByAppendingString:#" more string"];
self.one = [one stringByAppendingString:#" more string"];
Which is better using NSMutablestring or NSString ?
Sorry for long post, but I needed to understand these concepts.

For the first part of your question:
Almost definitely not. I expect the memory will be allocated dynamically, rather than released and reallocated.
If the previous answer is no, this is also, no.
The second and third options don't even work with the warning Incompatible pointer types assigning NSMutableString to NSString
I expect NSMutableString will be slightly more efficient in terms of memory as you are indicating early on that the program may need memory dynamically. NSString is likely to be allocated a single, suitably sized block of memory.
Your views of NSMutableString seem to be what the stringBy.. methods of NSString will do:
With NSString and its stringBy... methods, you are creating new objects, releasing the old one (if need be) and making the new object autorelease. (Take care if you are changing from non-autorelease to autorelease, you may have a release in your dealloc that isn't needed anymore)

NSString is a not mutable string object, which means, after initialization, you cannot change it, NSMutableString is mutable meaning you can append another string to it or other modifications.
when you do [two appendString:#"more string"], the pointer still pointed to the same location in memory and you don't have to worry about allocation or deallocation.
When you do two = #"string" , it means you make your string pointer pointed to a specific location in memory which contains static string with value "string" inside.
When you do self.two = #"string", you've already have a property named two declared. By using property in xcode, you don't have to worry about the memory since you've already specified in your property declaration. It is a nice tool xcode provide to you, and you should definitely use it whenever you can.

NSMutableString will save some memory as NSString objects are always constants. So reassigning a new value to an NSString variable will allocate new memory for the new string.
However, please note a few errors in your code. You will have to initialize the objects before sending messages to them:
// this won't work
NSString *one;
[one stringByAppendingString:#"more string"];
// nor this
NSMutableString *two;
[two appendString:#"more string"];
// first do this:
NSString *one = #"an initial string constant"; // or
NSString *one = [NSString string];
NSMutableString *two = [NSMutableString string];

NSString objects are immutable this means that when you "modify" a NSString you are in fact creating a new string and not modifying the old which is not very effective. With NSMutableString the string is kept in a buffer than can be modified.
So the simple rule is that if you need to modify the string in any way use a NSMutableString and if not NSString. You can also cast a NSMutableString to a NSString but not the other way around (then you need to make a copy)

Related

Objective C: Allocating Memory

I am new to Objective C and here is my confusion:
When is it applicable to allocate memory for an instance?. Like this:
When is it applicable to use this...
NSString *str = [[NSString alloc]init];
and to use this...
- (NSString *) formatStr:(NSString *) str{
NSString *str = (NSString *) str;
...
.....
.......
}
and even creating UIActionSheet, it uses alloc but in other UI elements, it does not..
What exactly the reason and when shall it be done?
Thanks fellas.. :D
In addition to the "normal" allocation route (i.e. through [[MyClass alloc] init]) some classes provide so called "factory methods". These are class methods that allocate objects internally. The advantage of using factory methods is that they can create a suitable subclass to return to the caller. In both cases, though, the allocation is ultimately done by alloc/init.
Objective C's alloc method handles allocating memory, you don't have to worry about allocating, just managing the retain and release cycles.
checkout this About Memory Management article from Apple
when you create an instance using alloc+init OR you get an instance through a method that has init in the name (a convention, e.g. initWithString) you are said to own the object, this is, you must not retain it (its ref counter is already set to 1) and need to eventually release it when you are done with it. When you receive an instance by calling a method which hasn't get init in the name (rule on thumb but you should always check documentation) this means that you are not the owner of the object, i.e. the object might be released at any time, even while you are using it. Usually methods such as stringWithFormat will return autoreleased objects which will be around until the end of the event cycle (unless you claim ownership by calling retain on the string).
I strongly recommend reading the cocoa memory management guide.
NSString *str = [[NSString alloc]init]; //you own the object pointed to by str. Its retain count is 1. If you don't call release this will be a memory leak.
- (NSString *) formatStr:(NSString *) str{
NSString *str = (NSString *) str; //you don't own str. btw, you don't need casting here
//using str here might throw exception if its owner has released it
[str retain]; //you own str now. you can do whatever you want with it. It's yours
.......
}

What happen when "retain" NSArray or NSMutableArray?

In the source codes
#property(retain) NSString* str;
#sythesize str;
self.str = newStr;
I understand actually following will happen
if( str != newStr ){
[str release];
str = [newStr retain];
}
So how about the case for NSArray or NSMutableArray ? Seem like it is complex,shallow copy and deep copy should be considered.
It's the same. Setting a property only changes the ownership of that array, not the content of the array (the content is owned by the same array). Therefore, only the array needs to be -retain'ed.
In fact, the runtime doesn't care about the specific Objective-C type of the property. The same setter procedure will be applied to every #property(retain) properties.
To make the setter perform shallow copying, make it #property(copy). There no way to make it deep-copy.

NSString *string = #"someString" vs NSString *string = [[NSString alloc] initWithFormat#"%#", string]

If I have a method
- (void) myMethod:(NSString *)string {
[Object anothermethodWithString:string];
}
and I call
[Object myMethod:#"this is a string with no alloc statement"]
Do I need to do something like
- (void) myMethod:(NSString *)string {
NSString *string2 = [[NSString alloc] initWithFormat:#"%#", string];
[Object anothermethodWithString:string2];
[string2 release];
}
instead of the way I had myMethod before? I have misbehaving code that seems to be caused by a string being auto-released while a second method within another method is being called (like in the example). The second way I have myMethod fixed all of my problems.
So is a "non-alloc" string an auto-released string? I asked this question as a follow up to another question (which was completely unrelated and is why I am creating this post), and a few sources said that I don't need to reallocate the string. I am confused, because the behavior of my code tells me otherwise.
Dave's got it right. You only need to worry about calling release on objects that you new, alloc, retain, or copy.
The above rule works very well, but if you're curious and want to get into a lot of detail, I suggest reading the Memory management Programming Guide from Apple's docs. It's free and goes from basic concepts into a lot of details.
If you use : NSString *str = #"". It is kind of a constant, you don't need to do any memory management.
If you call from a method : NSString *str = [NSString stringWithFormat:#""], the str is already autoreleased.
If you manually alloc, init. You need to call release, or autorelease yourself.
The general memory convention is : if you do something with new, alloc, retain, or copy, you need to release it yourself, any other cases, the object is autoreleased, don't release it

how do i swap two NSString variables (in a non garbage collected environment)?

I'm trying to swap two strings but I'm not sure if what I am doing is legal (coming from java I'm new to the whole retain count memory management).
Here's my code:
NSString *temp = [[NSString alloc] init];
temp = originalLanguageCode;
originalLanguageCode = translatedLanguageCode;
translatedLanguageCode = temp;
[temp release];
Is this allowed? I'm getting some strange bugs and I'm not sure what's causing them, hoping that this might be it. Any help is very appreciated, thanks!
After assigning a newly allocated string to temp you are immediately assigning originalLanguageCode to it, so the allocated string is completely lost. That is a memory leak. Then you are releasing temp, which was originally originalLanguageCode. This is an over-release.
Try this instead:
NSString *temp = originalLanguageCode;
originalLanguageCode = translatedLanguageCode;
translatedLanguageCode = temp;
Everything looks fine except that in your first line you're creating a string which you immediately leak on the second. You can just say:
NSString *temp = originalLanguageCode;
...
... and get rid of the [temp release] since you didn't create (and don't own) the object assigned to "temp."
Now you didn't say whether originalLanguageCode and translatedLanguageCode are instance variables. If so, use their accessors (which should themselves be doing the right thing with memory management).

Best way to initialise / clear a string variable cocoa

I have a routine that parses text via a loop. At the end of each record I need to clear my string variables but I read that someString = #"" actually just points to a new string & causes a memory leak.
What is the best way to handle this? Should I rather use mutable string vars and use setString:#"" between iterations?
You have to be careful in which case you create the NSString: (factory method) or (alloc init or (using #"").
If you use #"", it is a constant string, see here: Constant NSString
If you use [[NSString alloc] init], you need to release it.You just need to do [someString release].
If you use something like [NSString stringWithFormat:#""], you don't need to release it because it is already auto released by runtime
Since NSStrings are immutable, you cannot change the contents of the string. And by initializing it with #"" you're actually creating a constant NSString object.
You can either work with a NSString local to the loop, and release it in the end of the loop - or you can use a NSMutableString instead. I would prefer the loop local string though.
for ( ; ;) {
NSString* str = [[NSString alloc] initWithFormat:#"%#", CONTENT];
...
[str release];
}