Nature of NSString [duplicate] - objective-c

This question already has answers here:
Difference between NSString literals
(5 answers)
Closed 9 years ago.
Such a basic question, but i don't know the answer.What exactly the difference between:
NSString *str = #"Hello";
and
NSString *str = [[NSString alloc] initWithString:#"Hello"];
When should i use each one?

A #"" expressions is replaced at compile time1 with an instance of NSConstantString, which is a specialized subclass of NSString with a fixed memory layout2. This also explains why NSString is the only object that can be initialized at compile time3.
A [[NSString alloc]initWithString:#""] produces a NSString instance, initializes that instance with a literal expression, and releases the instance. Therefore, the object allocation is superfluous and immediately discarded. Which is why you should always use just the literal when creating immutable strings.
1 The LLVM code that rewrites the expression is RewriteModernObjC::RewriteObjCStringLiteral in RewriteModernObjC.cpp.
2 To see the NSConstantString definition, cmd+click it in Xcode.
3 Creating compile time constants for other classes would be easy but it would require the compiler to use a specialized subclass. This would break compatibility with older Objective-C versions.

When should i use each one?
NSString *str = [[NSString alloc] initWithString:#"Hello"]; //1st one
The above is redundant, and has same meaning as
NSString *str = #"Hello"; //2nd one
So always use shorter one. i.e 2nd one in my example.
EDIT:
Also see this What's the difference between NSString *s = #"string" and NSString *s = [[NSString alloc] initWithString:#"string"]?

Related

Understanding Instantiation in Objective-C

I’m currently trying to learn Objective-C by reading books and online tutorials, also referring to the Apple documentation but some things just don’t click. I have a question about classes, I have been using the NSString for a while now without putting too much attention on how it is used.
I was under the impression that in order for someone to be able to use a method from a certain class in Objective-C you first needed to instantiate it, something like…
ClasssName *varName = [[ClassName alloc]init];
Then you would call methods like...
[varName someMethod];
But looking at how the NSString is used I’m now I little confused, for instance here is how we would normally use it...
NSString *someString = #"some text here";
[someString stringByAppendingFormat: #"some text = %d", 3];
Following what I have read about classes we would need to do something like the following instead.
NSString *someString = [[NSString alloc]initWithString: #"some text here"];
[someString stringByAppendingFormat: #"some text = %d", 3];
Can someone explain why some classes do not require instantiation before using its methods?
Objective-C knows some abbreviations that are called literals. The compiler is aware of the special notation. A string literal is compiled into the binary and exits throughout the lifetime of an app.
For most cases it will behave like an object created on runtime.
if two literals are identical, only one object will be created and live forever
if you create NSString *string = [[NSString alloc] initWithString:#"My String"]; with #"My String" being used as a literal before, also string can point to it.
Since Apple LLVM Compiler 4.0 Objective-C knows some more literals. But in contrast to string literals these literals are created during runtime through convenient initializers.
Note that
[someString stringByAppendingFormat: #"some text = %d", 3];
does not change someString. It returns a new string object.
NSString *newString = [someString stringByAppendingFormat: #"some text = %d", 3];
The #"Text" syntax gives you an autoreleased string back, it can be thought of as a shorthand.
when you write
[[NSString alloc]initWithString: #”some text here”];
you conceptually create an autoreleased string with #”some text here” and then you create a retained new string with initWithString.

Objective-C: What is the difference between creating an object from alloc/init and class method calls?

For example,
NSString *string = [NSString stringWithString:#"a string"];
NSString *string = [[NSString alloc] initWithString:#"a string"];
and while we're talking about strings, is there any difference by setting up a string with:
NSString *string = #"a string";
?
As a final note, this isn't a specific question about NSString. I'm asking on a wider scope of all NSObjects.
There is no difference in ARC, but prior to it there was a difference: alloc/init returns an item with ref count of at least one that you'd need to release when you don't need it, while the class method returns an autoreleased item that you'd need to retain if you would like to keep it. The ARC compiler knows all this, and takes care of retaining/releasing for you based on your ownership specifications.

Basic difference between following NSString assignment calls

// Directly assigning the value.
NSString *str = [objDictionary objectForKey:#"attributeName"];
// Assigning with convenience method
NSString *str = [NSString stringWithFormat:#"%#", [objDictionary objectForKey:#"attributeName"]];
// Assigning after being owner to that object.
NSString *str = [[NSString alloc] initWithString:#"%#", [objDictionary objectForKey:#"attributeName"]];
In what cases, We need to identify which one needed to be used in code. ???
Any Reference links for difference between the same???
Or can someone answer the question in depth???
Thanks for the help.
NSString *str = [objDictionary objectForKey:#"attributeName"];
This is the declaration where you want to user local variable with autorelease memory assigned
i.e. you don't need to worry about memory allocation/deallocation.
NSString *str = [NSString stringWithFormat:#"%#", [objDictionary objectForKey:#"attributeName"]];
This method is useful when you need to combine different types in single string
i.e. integer/float with string
for e.g.
NSString *str = [NSString stringWithFormat:#"%# and %d", [objDictionary objectForKey:#"attributeName"], 5];
This will result in 'your value and 5'
NSString *str = [[NSString alloc] initWithString:#"%#", [objDictionary objectForKey:#"attributeName"]];
This is the assignment where you are allocating memory and you need to have that variable to use some other place so it will be there until and unless you release the memory of that variable.
Make sure when you allocate memory you release memory yourself as you are the responsible one.
For further detailed study I recommend you to visit documentation for NSString which will give you idea about available class/instance methods and how to use.
Assuming your dictionary contains a string, under ARC, these are all identical. With manual reference counting, the first two are autoreleased and the last one is retained.
For a reference guide, you can't do much better than the NSString class reference.

Assign to NSString after alloc/init

This doesn't seem to work:
NSString *string = [[NSString alloc] init];
string = #"%#M", anotherstring;
I expect this to make "string" equal to "5M" if "anotherstring" is "5".
Is this not the right syntax? Now, I could use initWithFormat and it would work, but how can you separate it into two different lines and also work?
There are two mistakes in your code. Firstly, NSStrings are immutable, and once you allocate and initialize them, they're set, and there's no way to change them. For that, you'd have to look into NSMutableString.
Secondly, the syntax of your code makes no sense. #"%#M", anotherString is not a valid Objective-C method call. You are indeed looking for -initWithFormat: to perform the operation you want. The code should look like this:
NSString *string = [[NSString alloc] initWithFormat:#"%#M", anotherString];
Read more about NSString and how to use it in the NSString Programming Reference document, and the String Programming Guide to get a sense of how to work with strings in Cocoa and Objective-C.
This line:
string = #"%#M", anotherstring;
is syntactically correct, but it doesn't do what you want it to do. This is how you format a string:
NSString *string = [[NSString alloc] initWithFormat:#"%#M", anotherstring];
There's no point in separating it into two lines. This:
NSString *string = [[NSString alloc] init];
string = [[NSString alloc] initWithFormat:#"%#M", anotherstring];
will create an extra NSString object, and also cause a memory leak.
How about
NSString* string;
string = [[NSString alloc] initWithFormat:#"%#M", anotherString];
Keep in mind that the = operator is assignment. Any time you use it, any value was stored in your variable is overwritten with the new one. So even if your original code was syntactically correct it still has faulty semantics that would, in this case, cause a memory leak.
just make it into a property and you dont need to worry about releasing and retaining the "string" (that is if you autocreate it by using synthesize). and dont forget to autorelease the object ur assigning to the property:
self.string = [[[NSString alloc] init] autorelease]

NSString retain Count

Just couple of days i was working on a project and i have to see what is retain count of a string.
But it always return me "2147483647", Why it is so?
Check out this code to check it yourself.
NSString *str = [[NSString alloc] initWithString:#"Hello World"];
NSLog(#"String Retain Count: %i", [str retainCount]);
So my question is why it is not returning 1 like other objects return, why i am getting "2147483647"
Thanks in advance.
The compiler is smarter than you.
It sees #"Hello world" and thinks "Aha! A constant string!"
It then sees [[NSString alloc] initWithString:#"Hello world!"] and thinks "Aha! An immutable object created with a constant string!"
It then collapses both of them down into a single NSConstantString, which has a retainCount of UINT_MAX, so that it can never be released.
NSString *str = [[NSString alloc] initXXX
usually would allocate some RAM and return you a pointer. This RAM would then be subject to releases and reatins. However, when you do:
NSString *str = [[NSString alloc] initWithString:#"Hello World"];
the string returned is #"Hello World", which is already allocated because it was a string literal. Since it is a string literal, there is no way to release it, and thus the system has to mark it as unreleasable. The way it does that is to set its retain count to the max integer value.
NString *str = [[NSString alloc] initWithFormat:#"Hello World. Today is #%", todayDate];
This string will have a retainCount of 1. Although there is a string constant in there, it is appended to by another string. Since you can't modify that constant string, a copy of the "Hello World. " string is made, and the content of the todayDate string is added to that. That memory now is given ownership to the caller, with a retainCount of 1.
The string is being optimized at compile-time to a statically allocated instance of NSString in order to save on some variable overhead and the like. You're seeing such a high retain count because static strings have a retain count of the maximum integer on whatever platform you're developing on.