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

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

Related

Usage of NSMutableString vs NSString?

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)

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
.......
}

retainCount shows MaxInt

After trying to print retainCount of object I get 2147483647. Why do I get such a result? It should be 1, shouldn't?
NSString *myStr = [NSString new];
NSUInteger retCount = [myStr retainCount];
NSLog(#"refCount = %u", retCount);
2011-09-08 17:59:18.759 Test[51972:207] refCount = 2147483647
I use XCode Version 4.1. Tried compilers GCC 4.2 and LLVM GCC 4.2 - the same result.
Garbage Collection option was set to unsupported.
NSString is somewhat special when it comes to memory management. String literals (something like #"foo") are effectively singletons, every string with the same content is the same object because it can't be modified anyway. As [NSString new] always creates an empty string that cannot be modified, you'll always get the same instance which cannot be released (thus the high retainCount).
Try this snippet:
NSString *string1 = [NSString new];
NSString *string2 = [NSString new];
NSLog(#"Memory address of string1: %p", string1);
NSLog(#"Memory address of string2: %p", string2);
You'll see that both strings have the same memory address and are therefore the same object.
This doesn't directly answer your question, but retainCount is not really all that useful and should not be used for testing. See this SO post for details.
When to use -retainCount?
While NSString's are an odd case (there are others in the framework) you might also run across this in other clases - it's one of the ways of creating a singleton object.
A singleton only exists once in the app and it's pretty important that it never gets released! Therefore, it will overwrite some methods of NSObject including (but not limited to):
- (id)release {
// Ignore the release!
return self;
}
- (NSUInteger)retainCount {
// We are never going to be released
return UINT_MAX;
}
This object can never be released and tells the framework that it's a singleton by having a ludicrously high retain count.
Checkout this link for more information about singleton objects.
I've seen this a couple of times regarding NSStrings, the retainCount returns the maximum count instead of the actual one when you try to look at retainCounts of strings in this manner.
Try this;
NSString *myStr = [[NSString alloc] init];
NSUInteger retCount = [myStr retainCount];
NSLog(#"refCount = %u", retCount);
Edit: Restored NSUInteger

NSString stringWithFormat causing iPhone app to crash

When I construct a dynamic URL using NSString stringWithFormat and then use that value in my XML parser I get random crashes. However if I test it with a constant string it works fine...
This is my code for generating the string,
loginURL = [NSString stringWithFormat:#"%#%#",ScriptURLString,#"authenticate"];
Which results in,
http://edms.digistorm.com.au/test/index.php?s=&sc=D41D8CD98F00B204E9800998ECF8427E&m=authenticate
Then I use it in my XML parser,
XMLReturnData = [[NSMutableArray alloc] init];
xml = [[XMLParser alloc]
initWithXMLPath:loginURL
lookForElement:#"Authenticate"
setCallbackObject:self
withSelector:#selector(dataReady)
data:XMLReturnData
];
For some reason this is causing my app to crash. If I use a constant string like,
loginURL = #"http://edms.digistorm.com.au/test/index.php?s=&sc=D41D8CD98F00B204E9800998ECF8427E&m=authenticate";
it works fine...
loginURL is defined as NSString *loginURL; inside my header file for this view.
Any help or guidance would be much appreciated!
Thanks,
Tim
The method you are using to allocate the string is important.
You have two basic ways to allocate your string:
NSString *loginURL = [[NSString alloc] initWithFormat:#"%#authenticate", ScriptURLString];
Compared to:
NSString *loginURL = [NSString stringWithFormat:#"%#authenticate", ScriptURLString];
For the first, Cocoa conventions say that because you caused the object to be created via an alloc message you "own" it and are responsible for releasing it.
For the latter, the convention is that because you caused the object to be created by a class "convenience" method, you do NOT own it and are not responsible for releasing it. The class (here, NSString) has that responsibility which it will discharge through an autorelease pool.
To summarise, when you explicitly create something with an alloc/init, you must release it. When you use a [NSThing thingWithXXX] style method you must not.
This shows your string is get released and when you calls it in XML parser it crashes the app.
actually stringWithFormat gives a autorelease object for string.
So what you need,make your string as retain property inside .h then synthesize it in .m and release it in dealloc method.
and also do this,
in viewDidLoad
NSString *tempString=[[NSString alloc] init]; //using this because your string is retain type so it prevent increment in retain count.
self.loginURL=tempString;
[tempString release];
Now when you use stringWithFormat use like this
self.loginURL = [[NSString stringWithFormat:#"%#%#",ScriptURLString,#"authenticate"] retain];
It solves your problem.
Not to call release on loginURL, because you have'nt alloced it and only iOS have right to destroy it...
Use below code
loginURL = [[NSString alloc] initWithFormat:#"%#%#",ScriptURLString,#"authenticate"];
Once you used loginURL Do'nt forget to call release on it ...
[loginURL release];
Try this, it might help you.
loginURL = [NSString stringWithFormat:#"%#authenticate",ScriptURLString];

How does autoreleasing work in Objective-C?

I am just reading through the Practical Memory Management guide.
I am somewhat confused by this block of code:
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
It seems to me that string is going to have a reference count of 0. Is this true?
What stops string from being deallocated before we call NSLog(string)?
Is this somehow equivalent to this:
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
Edit: Similarly this code is given in the Practical Memory Management
guide:
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:#"%# %#", firstName, lastName];
return string;
}
When and how does the return value get freed? Who is the owner? Does the caller of fullName need to release the string returned by full name?
Strictly speaking,
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:#"Hello"];
NSLog(#"%#", string);
}
Is not equivalent to
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:#"Hello"] retain] autorelease];
NSLog(#"%#", string);
}
The convention is that a method should autorelease any object it returns. The only exception (AFAIK) is for constructors, which return an object with a +1 retain count. Since [NSString stringWithFormat:] returns an object. In first snippet, stringWithFormat: returns an already autoreleased object. the second snippet, you're retaining it once more and it'll be released twice (which has the same effect, but the second retain/autorelease pair is redundant).
Ok, now to answer your question. Essentially, every time UIKit calls your code, it creates an NSAutoreleasePool object. Every time you autorelease an object, its added to this pool. Finally, when your code returns back to UIKit, it calls the drain method on the pool (i.e [pool drain]) and that releases every object which has been added to the pool and deallocates the pool. Also, autorelease pools can be nested, so you can create your own pools and drain them if you're going to be creating a lot of autoreleased objects. It isn't as complicated as it sounds.
I'd highly recommend that you read the Autorelease Pools chapter in the Memory Management Guide (Which incidentally, comes right after the Practical Memory Management chapter).
First of all:
NSLog(string);
Don’t do this. (I just realized it comes right from the Apple docs. Weird.) The first argument to NSLog is the formatting string. If your string contains some percent escapes, bad things will happen. The correct, if slightly longer way is:
NSLog(#"%#", string);
Now to the point: Autoreleased objects do not have zero retain count. They have retain count 1+ and have a pending –1 operation on them that will happen “soon in the future”.
The precise meaning of “soon in the future” depends on the situation. If you’re on the main thread and there is no additional autorelease pool in place, autoreleased objects will be released on the next runloop iteration. This does not have to be the case if you have an additional release pool:
// Let’s pretend this is a long loop and you don’t want to wait
// for the autoreleased objects to be collected by the main pool.
for (…) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *foo = [NSString stringWith…];
[pool drain];
// Now foo is no longer valid.
}
As for returning autoreleased objects, that’s one of the main use cases for autoreleasing. You are returning an object that will perish “soon”, but if the caller is interested, he can retain and take over the ownership. (It’s like, if you pardon the image, passing a bomb with a burning safety fuse. If the caller is interested, he’ll put out the fuse by retaining.) And if the caller is not interested, like maybe he’s ignoring an output from a function or just uses the value to construct some other object, he does not do anything and the object will get out of memory:
- (id) createObject {
return [NSString stringWith…];
}
- (void) interestedCaller {
NSString *value = [[self createObject] retain];
}
- (void) notInterestedCaller {
[self createObject]; // maybe just interested in side effects
NSString *differentString = [NSString stringWithString:[self createObject]];
}
This is really convenient and makes the manual memory management quite pleasant. You might be interested in run loops and the Objective-C tutorial by Scott Stevenson.