What does #"some string" mean in objective-c? - iphone

I'm just starting out with iphone development and ran across some example code that used #"somestring"
someLabel.txt = #"string of text";
Why does the string need the '#'? I'm guessing it's some kind of shortcut for creating an object?

It creates an NSString object with that string as opposed to the standard c char* that would be created without the '#'

In Objective-C, the syntax #"foo" is an immutable, literal instance of NSString.

Just an interesting side note... NSString literals created by using the #"..." notation are not autoreleased. They essentially just hang around until your program terminates.
Just a caution that if you want to maintain control over whether or not this object gets released (freed) down the road you may want to consider using something like:
[NSString stringWithString:#"..."];
...instead. This would create an autoreleased version of the same string that will be freed from memory next time the "autorelease pool is drained".
Just food for thought.
Cheers-

Related

Directly use of NSString

I find I usually directly use a NSString like:
self.text = #"word";
label.text = #"word";
function(#"word");
I think it is a wrong way to directly use NSString, because the #"word" will have a retainCount of 2 after it has been used. Is that right?
What is exactly the retainCount of #"" ? Is it an autorelease object or has a retain of 1?
What`s more, I encountered some memory leak as the pic shown below:
I suspect it is related to the direct use of the NSString.
Essentially, the retain count of NSString literals is infinite. The memory for these objects is reserved by the compiler at compile time and never gets released for the duration that your app is running, no matter how often you try to retain or release them.
This is another good example why it is wrong to care about retain counts. You should only care about the golden memory management rules: if you take ownership of an object (with alloc, new, copy or retain), you have to release or autorelease it later. Otherwise, you don't.
Quoting from String programming guide
The simplest way to create a string object in source code is to use the Objective-C #"..." construct:
NSString *temp = #"/tmp/scratch";
Note that, when creating a string constant in this fashion, you should avoid using anything but 7-bit ASCII characters. Such an object is created at compile time and exists throughout your program’s execution. The compiler makes such object constants unique on a per-module basis, and they’re never deallocated, though you can retain and release them as you do any other object.
the #"word" will have a retainCount of 2 after it has been used. Is that right?
No. This is a perfect illustration of why it is bad to think in terms of retain counts which are an internal implementation detail. You can think of string literals as strings that are "owned" by the executable image so they will not go away. You should treat them like any other Objective-C object.
If you do take a sneaky peek at the retain count of a string literal, you'll find it is set to some really big number (something like the maximum value for an NSInteger). This is treated as a special value by retain and release that they don't change.
The memory for string literals is allocated as part of the binary image at compile time. It can never go away. Your memory leak is not because of this.
No, it's a good thing to declare an autoreleased NSString by using directly #"". But NSString are retained in a particular way and it's not really possible to know what's being done at runtime. You may have weird retain count sometimes. Don't bother about your leak of 48 Bytes.... It's not related to your nsstring.

When to write "NSString *str" or "NSString str"?

I'm learning Objective C to program on iOS.
I know it has something to do with pointers, which I fail to understand.
I don't know what's the difference of creating a string (or any NSObject) like this:
NSString place = ...;
or
NSString *place = ...;
Thanks for the help!!
You never write NSString str. Period. All Obj-C objects are actually C pointers.
NSString is a class and as such instances of the class declared as NSString *str must always be declared as a pointer (since object instances can only be accessed via a pointer to the objects structure). Therefore this declaration is illegal: NSString str
Objective-C is, in some sense, more like a scripting language. Class definitions are maintained during runtime and can be modified. There is a C interface to the class definition system in objc.h. Even system classes can be modified, though it is not a good idea to do so. Because of this, all Objective-C objects must be created at runtime and accessed via pointers. To put it another way, there is no way for the compiler to know what an object should look like at compile time. This is also why "object may not respond to selector" is a warning, not an error and has the word "may" in it.

String declarations and assignments: 3 methods

For non-retained string declarations, are these three lines the same?
NSString *list2 = self.map;
NSString *list2 = [NSString stringWithFormat:#"%#", self.map];
NSString *list2 = [NSString stringWithString:self.map];
They all create an autoreleased string object, right? Is there a preferred method among these, or are there any differences in the memory usage or behavior of "list2" depending on these methods?
For some reason, I find the manipulation of strings in objective-C the most confusing transition from other languages.
The simple fact, You don't own the object in the above three cases,
So you could use either,
This is more related to choice of developer then performance.
Go through the Memory Management Programming Guide
They all create an autoreleased string object, right?
No, the first one merely assigns the pointer returned by string.map to list2. The second and third ones theoretically create new NSStrings that you don't own and assign them to list2. However, if string.map returns an immutable string, the third one will probably give you the same pointer (possibly retained and autoreleased).
In all cases you do not own the (new) string. That's actually all you need to know. They may be autoreleased, but it is not relevant to you using them.

NSString vs NSMutableString with stringByAppendingString

So, I'm fairly certain that if I plan on manipulating strings often, such as with stringByAppendingString, I should be using variables of type NSMutableString.
But what if I'm doing something like this?
UILabel *someLabel = [[UILabel alloc] init];
[someLabel setText: [[someDictionary objectForKey:#"some_key"] stringByAppendingString:#"some other string"];
I read that if you use stringByAppendingString on an NSString, you end up with leaks because the pointer associated with the initial NSString moves around, pointing to the new string created by the append, whereas with NSMutableString, your pointer always points to that mutable string.
So my question is, what is implicitly happening when I call stringByAppendingString on something that is a string, but not explicitly an NSString or an NSMutableString? Such as, in my above case, the value of some key in a dictionary. Is doing this wrong, and should I be doing something like below?
[[[NSMutableString stringWithString:[someDictionary objectForKey:#"some_key"]] stringByAppendingString:#"some other string"]]
I read that if you use
stringByAppendingString on an
NSString, you end up with leaks
because the pointer associated with
the initial NSString moves around,
pointing to the new string created by
the append, whereas with
NSMutableString, your pointer always
points to that mutable string.
That sounds like the advice of someone who didn't quite have a grasp of what is going on with the memory management. Sure, [NSString stringByAppendingString] returns a new string. But what you do with that new string is up to you. You could certainly cause a memory leak by reassigning the result to a retained property in a careless fashion, like so:
myStringProperty = [myStringProperty stringByAppendingString:#" more bits"];
The correct form would be to use self, like so:
self.myStringProperty = [myStringProperty stringByAppendingString:#" more bits"];
Follow the cocoa memory guidelines.
As for dictionaries and other collection types: treat what comes out of the dictionary appropriately given the type you know it to be. If you pull an object out which is actually an NSString, but try to use it as a NSMutableString, your app will fall over (with 'selector not found' or similar). So in that case, you do need to make a new NSMutableString from the NSString.
Interesting note: Apple chose to make NSMutableString a subclass of NSString. Something about that seems unwise to me -- if something looks to be immutable, because it has type NSString, I want it to be immutable! (But in fact it could be NSMutableString.) Compare that to Java, which has a String class and a completely separate BufferedString class.
I've always been a fan of [NSString stringWithFormat#"%#%#", a, b]; because then you clearly get a new autoreleased string and can dispose of "a" and "b" correctly.
With [someDictionary objectForKey:#"some_key"], you will be getting the type of object that was put into that dictionary originally. So blindly calling stringByAppendingString without knowledge of what's in that dictionary seems like a bad idea.
-stringByAppendingString is going to return you a new NSString that is distinct from both strings involved. In other words:
NSString *string3 = [string1 stringByAppendingString:string2];
string3 is an entirely new string. string1 isn't changed at all, nothing happens to its memory location or contents. The person who told you that probably just misunderstood what was going on.
[mutableString1 appendString:string2];
In this case, mutableString1 still points at the same object, but the contents of that object have been altered to include string2.
One last thing to keep in mind is that if you are using mutable strings, you should be careful with sharing references to it. If you pass your mutable string to some function which keeps a pointer to that mutable string and then your code changes that mutable string at some point in the future, the other reference is pointing at exactly the same object which means the other code will see the change as well. If that's what you want, great, but if not you must be careful.
One way to help avoid this problem is to declare your #property statements for NSStrings to be "copy" instead of "retain". That will make a copy of your mutable string before setting it in your property and the -copy method implicitly gives you a NON-mutable version, so it'll create an NSString copy of your NSMutableString.
If you follow the rules for memory management, you will be fine using stringByAppendingString. In a nutshell:
if you own an object, you need to release or autorelease it at some point.
you own an object if you use an alloc, new, or copy method to create it, or if you retain it.
Make sure you read up on Apple's Memory Management Rules.
In the first code sample in your question, you aren't using alloc, new, copy or retain on any of the NSStrings involved, so you don't need to do anything to release it. If outside of the code that you've included in the sample you are using alloc, new, copy or retain on any NSStrings, you would need to ensure that they are released later.

Does XCode creates one object for all empty strings?

i've noticed that all #"" objects create one reference for all times it is executed.
NSString *s1=#"";
NSString *s2=#"";
In this sample s1 equals s2.
#"" will create one pointer in all cases, every time i use it?
Can i rely on this feature in comparing strings in objective-c?
Or simply, can i use this statement, if i want to assure that my string is empty:
if(s == #""){
//do something
}
Yes Objective C has an optimization in the compiler that simply points all equivalent string literals to the same string in memory to avoid allocating unnecessary resources. This feature is reliable but there is a chance that this will not always happen as documented in the Objective C language specs.
you should use
if([s isEqualToString:#""])