NSString property making a shallow copy - iphone

I am having some trouble understanding what is going on with these two string properties declared in separate classes:
#property (nonatomic, copy) NSString *userPhone;
and
#property (nonatomic, copy) NSString *userLogin;
Somewhere in the code I go and do the following:
user.userPhone = self.userLogin;
What I would expect is that userLogin gets copied into a new object and assigned to userPhone. However, I found out that they both share a reference to the same object! So when userLogin get released, so does userPhone, breaking my poor app.
I know that I am missing something about memory management here, but I don't understand why copy does not work in this case.
Anyone knows?
Thanks a lot

NSString objects are immutable, meaning that their contents can not change once they have been created. To exploit this, the copy method does not create a new string. Instead, it retains the original string*. This is an internal optimization, from your point of view standard memory management rules apply. If you have problems with the string being deallocated before you expect, you must be over-releasing it somewhere else.
stringWithString: is also internally optimized in the same manner. If you pass an immutable string as the argument, it will not create a new one*. If you execute the following code, you will see that string1 and string2 addresses are the same.
NSString *string1 = #"Test";
NSString *string2 = [NSString stringWithString:string1];
NSLog(#"%p, %p",string1, string2);
(*) These are implementation details that are subject to change at any time.

You may be double releasing the original. If i remember the copy property will actually just retain an immutable copy (i.e NSString) and only do a hard copy if it is mutable (NSMutableString). Its possible the original string is autoreleased and you give it a hard release, accounting for two decrements.
Edit:
After reading other posts i have changed mine to reflect.

Related

get the value of a NSString variable

I have a weird problem.
pictureLink is a global variable declared in .h
NSString *pictureLink;
}
#property(retain,nonatomic) NSString *pictureLink;
i wrote this code
NSString * myPictureUrl=[NSString stringWithFormat:#"http://mywebsite.com/uploads/%#.jpg",hash];
pictureLink=myPictureUrl;
I have a strange result, it must be a pointer
Or
pictureLink=[NSString stringWithFormat:#"http://mywebsite.com/uploads/%#.jpg",hash];
i have EXC_BAD_ACESS error
It's memory management fault, you're not retaining myPictureUrl in your code.
[NSString stringWithFormat:#"http://mywebsite.com/uploads/%#.jpg",hash]; returns an autoreleased value, so you have two options:
pictureLink=myPictureUrl; should look like [self setPictureLink:myPictureUrl];.
do a [myPictureUrl retain];, and don't forget to release it later.
Consider using ARC (Automatic Retain Counting) for you project. With ARC the compiler takes care of retain counts so you don't have to, in fact aren't allowed to. There is a refactoring that will convert a current project.
You are bypassing your #property by calling directly the variable, so no magic provided by your #property settings is done, like retain and release.
you need to do self.pictureLink to use the #property.
To avoid the temptation of accessing directly my variable I do the following
NSString *theProperty
}
#property (nonatomic, retain) NSString *property;
and
#synthesise property = theProperty;
That way if I go around the #property I really, really wanted to do it.
But you need a very, very, very good reason to do so, and event then, it may not be a good enough reason.

Do I use retain or copy in my singleton?

I read somewhere that with NSString in an object, one has to use copy instead of retain. Can someone explain if this is correct and why?
For example I have the following declaration for my singleton:
#import <foundation/Foundation.h>
#class FaxRecipient;
#interface MyManager : NSObject {
NSString *subject;
NSString *reference;
NSString *coverSheet;
FaxRecipient *faxRecipient;
}
#property (nonatomic, retain) NSString *test1;
#property (nonatomic, retain) NSString *test2;
#property (nonatomic, retain) NSString *test3;
#property (nonatomic,retain) FaxRecipient *faxRecipient;
+ (id)sharedManager;
#end
I think "has to" in the sense of must is a little strong. You can use either copy or retain, but you should generally use copy for your NSString* properties because:
You usually don't want a string property to change under your nose;
NSMutableString is a subclass of NSString, so it's entirely possible that someone might set your NSString* property to point to a mutable string, thus creating the potential for the string to be changed while you're using it;
For immutable classes like NSString, copy operations end up just retaining the original object anyway.
Considering those three points, it's hard to think of a good reason to use retain instead of copy for your NSString properties.
prefer copy. it does not matter whether your class is or is not a singleton.
i wrote a fairly lengthy explanation for this, which details mutable and immutable types here:
NSMutableString as retain/copy
You can also use copy instead of retain. I use copy for NSString. There is good discussion on this topic. Here is a stackoverflow post NSString Copy or Retain?
You could use either,In both cases you will be owner of the objects and need to be released in dealloc.
Difference between copy and retain .
retain :--> It just increase the retain count on the exist object.
copy :--> it crate the new object for your property
In both cases: you will have the ownership of objects.
Read Apple memory management concept.
# Claus Broch: From Apple Documentation
You take ownership of an object if you
create it using a method whose name
begins with “alloc”, “new”, “copy”, or
“mutableCopy” (for example, alloc,
newObject, or mutableCopy), or if you
send it a retain message.
You should use the retain value in this instance. The reason for this is that
1. you don't want the object to be deallocated
2. you are most likely going to want to change the value of the NSString at some point
Using the copy attribute is basically saying that the value of your NSString should not change without warning. i.e. it will stop the value of the NSString being set and retrieved at the same time.
For this implementation, you should use retain, or at least thats my understanding. For more look here: http://cocoawithlove.com/2010/06/assign-retain-copy-pitfalls-in-obj-c.html

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.

When to use retain and when to use copy

I'm confused about which to use and when. Is there a rule of thumb? Can in most cases either of them be used? Any special rules?
#property (nonatomic, retain) NSDate *theDateFromPicker;
#property (nonatomic, copy) NSDate *theDateFromPicker;
In this case which would be the best choice?
Thanks
-Code
You'll want to use copy when you don't want the possibility that the object gets modified by another object.
A good example is NSString. Let's say you have this code:
#property (nonatomic, retain) NSString *aString;
// in some other class
NSMutableString *mutableString = [[NSMutableString alloc] initWithString:#"test"];
theObject.aString = mutableString; // theObject retains the mutable string
[mutableString setString:#"test2"];
What happens here is that you assign the value "test" to aString, but then it gets modified externally and it becomes "test2", because you retained the mutable string. If you had set copy, this wouldn't happen, because you are making a copy of the mutable string.
NSDate is immutable and we don't have a mutable subclass at this time. So retain is fine. Copy won't hurt either, and indeed I expect copy to just hand back the very same instance here (retained once more).
The reason for using copy at NSString is that you might get a NSMutableString passed to your object instead which might change right under your feet. This cannot happen here.
In iOS, you'll usually work with single thread so there is no chance that your object gets modified concurrently.
Moreover even if you specify copy the property can still be modified by just setting it again.
The rule of the thumb is: "use retain on iOS"
However there are few situations that using copy is required/advised:
you must use copy if you accept Blocks (blocks of code added with iOS4) as the blocks need to be copied to heap before retaining (see Copying blocks (ie: copying them to instance variables) in Objective-C for more details
if you writing code that will be executed in background it is safer to use (atomic, copy).
you should consider using copy if you want to make sure that only assigning to the property changes it value. (it could be useful if you implement KVO)
The rule of thumb is use copy if the class implements the NSCopying protocol unless you have good reason not to. The only good reason I can think of is performance. For instance, technically you should use copy for NSMutableArray properties, but as you can imagine, copying large mutable arrays will get expensive in CPU time and memory.
With copy you'll have 2 different objects.
So if you modify one, the other won't be modified.
Copy gives you a separate object.
In general, you should just be using retain, unless you explicitly want to make copies of objects. Each time you copy you have to release, so keep that in mind.
A good time to use -copy is when you're going to be using enumeration to add or remove objects.
Take an array, for instance. If you are enumerating the array, you can't add or remove objects to it during the enumeration, or you will crash. Before starting enumeration, use -copy to create a new copy of the array, and as you're enumerating, if you need to add/remove an object (mutate), you can do so on the copy.
When you're finished with the enumeration you can set the copy back to the original.

iPhone Dev - NSString Creation

I'm really confused with NSStrings. Like when should I do
NSString *aString = #"Hello";
of should it be:
NSString *aString = [[NSString alloc] initWithString:#"Hello"];
But then its different when you're assigning a value to an NSString property isn't it?
Can someone clear this up for me?
Thanks!!
In general you should do the first, but they are mostly functionally the same. You can treat constant NSStrings just like normal NSString string objects, for instance:
[#"Hello" length]
will return 5. You can assign them to properties, everything just works. The one thing you might notice is that with the constant NSStrings you don't have to worry about retain/release. That is because they are actually mapped into the applications readonly data section, and don't have allocated memory. Retain and release calls against them still work, they just become noops.
NSString *aString = #"Hello";
Will create an autoreleased string. That is, if you don't explicitly retain it, it will might disappear after your method is over (and sometimes that's totally fine). But if you want to hold on to it past that time, you'll need to retain it.
If you create a property for that string like this
#property (retain) NSString *aString;
And then assign like this:
self.aString = #"Hello";
Then you've properly retained the string and it will stick around.
On the other hand, using alloc, init will create a string for you with a retain count of 1, and if you don't need it past that method, you should release it.
****Edit: #"Hello" is not an autoreleased string, as others have pointed out. My bad. ****