When to use retain and when to use copy - iphone

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.

Related

Need to retain, and synthesize NSStrings?

I'm a bit confused as to whether NSStrings should ever be retained and synthesized. I have a NSString value as an instance variable, and am retaining and synthesizing it. But I am assigning it different values such as:
self.value = #"VALUE";
....
self.value = #"DIFFERENT_VALUE";
I'm not actually calling alloc anytime. Do I need to retain and synthesize this variable then?
You can think of on-the-fly strings as autoreleased in terms of how you use them, although in reality they will probably stay around as fixed values... because you are using the accessors they will automatically get copied or retained (however you marked the accessor) and so you do need to release them in dealloc.
As for the need to #synthesize, remember all that is doing for you is actually creating the get/set methods that take the variable and place it in your iVar. So not matter what you either need to #synethsize a property OR create the get/methods yourself - usually far better just to use #sythesize.
You should as you'll never know how you are going to change the use of the code in the future. Change the code to use dynamically created strings, and it will break if don't follow the rules.
Also note that the best practice for NSString is to set it to copy instead of retain. The reason is simple, this prevents the string from being changed under your feet.
See NSString property: copy or retain? for more details.
If you have never alloc'ed them, you usually don't need to retain, but if they are instance variables in your objects, they are probably marked as retain or copy so at your object's dealloc method you should release these objects if there is a value on it.

NSString property making a shallow copy

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.

ObjectiveC ivars or #property

Working on iPhone, after a lot of headache and memory problems I just realized from other examples that we do not need to necessarly create #properties for each instance variable we define in header file. And actually I found out ivars easy to just allocate and release it after I use anywhere in the class, for #properties I have to use autorealese or I have serious problems and becareful how I allocate..
For instance for objects below, #properties(retain/copy..) is not used in headers in many examples;
{
NSURLConnection *connection;
NSMutableData *xmlData;
NsMutableString *string
}
But for some strings or object types #properties is used, I know that when we set #property cocoa creates some setters getters which are handling the relasing and retaining of the objects. But seems like as for xmlData or connection instance variables we do not need that and they do their job like this.
Are there some reference guidelines I can keep in mind on deciding whether or not to create #property's or just use simple ivars?
My only problem when using properties is not becuase I am lazy to define it, but when I carefully allocate and init them in code, I have to use autorelase and dont feel like I have the control when to release reset and allocate it again, and it gives me one more thing to worry about while and when and how should I release, reset it. I find ivars I can alloc and release anytime once anywhere easily without worrying about anything..or I am missing other things here.
Tnx
There seem to still be some misconceptions flying around about properties.
that we do not need to necessarly create #properties for each instance variable we define in header file
Correct. You can use private instance variables directly in your implementation file. However, since synthesized properties come with free memory management, you might as well take advantage. My rule of thumb is to use the ivar directly until the first time I find myself writing:
[ivar release];
ivar = [newIvar retain];
As Sam says, there is already a potential bug there if iVar == newIVar. This is the point at which I switch from using ivars directly to creating a property. However, I put the declaration of the new property in a class extension in the implementation file. This means that the property is officially not part of the public interface (and will cause compiler warnings if used accidentally).
when we set #property cocoa creates some setters getters which are handling the relasing and retaining of the objects.
Actually, no. The #property just declares a property. In order to automatically generate the getter and setter, you need to #synthesize it. You could, alternatively write your own getters and setter which do not even have to reference a real ivar.
Technically, you should not use the property in the init or dealloc methods because a subclass might have overridden them or (in dealloc) you might set off a KVO notification.
From Sam's answer and comments
If you want a property regardless, you could use a private interface at the top of the implementation file
As I say above, private categories have sort of been obsoleted by class extensions (which is near enough the same thing but allows you to put the implementation of the methods in the main class implementation).
If you want the benefits of using dot notation shorthand
Some of us would argue that there are no benefits to dot notation. It's a gratuitous and needless pollution of the struct member syntax. However, dot notation has no relation to #property declarations. You can use dot notation for any accessors no matter how they were declared, provided they adhere to the pattern -foo and and -setFoo:
Create properties only for variables that need to be accessed from outside the class. Any class variables that are used internally need not have getters/setters defined.
Generally speaking an abundance of properties indicates high coupling and poor encapsulation. You should restrict what variables your class exposes in the interface.
EDITED to respond to comment:
Using properties over direct access may be preferred because it gives you easy memory management.. for example:
// interface
#property (retain) Object *someVar;
// implementation
self.someVar = otherVar;
is the same as
// implementation
if (_someVar != othervar)
{
[_someVar release]
_someVar = [otherVar retain];
}
However you should not needlessly expose vars in your interface because it opens the class up for people to use in the wrong way.
If you want a property regardless, you could use a private interface at the top of the implementation file
#interface TheClass(Private)
// private stuff
#end
First of all, let me say that Sam's answer is complete, IMO, and gives you clear guidelines (+1 from me).
My only problem when using properties is not becuase I am lazy to define it, but when I carefully allocate and init them in code, I have to use autorelase and dont feel like I have the control when to release reset and allocate it again, and it gives me one more thing to worry about while and when and how should I release, reset it. I find ivars I can alloc and release anytime once anywhere easily without worrying about anything..or I am missing other things here.
You should not worry about autorelease in the following idiom:
self.stringProperty = [[[NSString alloc] initWith...] autorelease];
because this is the way that things are meant to work;
EDIT: [the above statement has several parts:
the object is allocated and initialized (retain count is 1);
immediately, the allocated object is also autoreleased; this means that the object will be released automatically, (more or less) when the control flow gets back to the main loop;
in the very same statement, the allocated object is assigned to a retained property, self.stringProperty; this has the effect of (once again) incrementing the retain count;
So, it is true that autorelease adds some "ambiguity", because the object will be released at a time that you don't know precisely (but pretty soon anyway), but assigning to the retain property will increase the retain count so that you have full control over the lifetime of the object.]
If you don't like the autorelease you can always use a constructor method which gives you back an autoreleased object, when available:
self.stringProperty = [NSString stringWith...];
or assign directly to the ivar:
stringProperty = [[[NSString alloc] initWith...] autorelease];
because by accessing directly the ivar you are bypassing the setter and getter. Anyway, do the it only in this case (IMHO) to avoid ambiguities.
More in general, the autorelease glitch is the only drawback that using properties has over directly accessing the ivars. The rest are, IMO, only advantages that in many cases will save your life, and if not your life, a leak or a crash.
There is nothing you cannot do with directly accessing the ivars and taking care of when it is necessary to release before assigning, or not forgetting to set to nil after releasing, etc., but properties will do that easier for you, so my suggestion is simply use them and accept the autorelease shortcoming. It's only a matter of getting the basic "idioms" right.
It has long been custom to access ivars directly. That is, IMO, fine from inside the same class, although many properties are classes and then properties provide protection against retain/release issues.
IMO, it is, however, preferrable to encapsulate most ivars into properties, especially those that have retain/release semantics, but also those that need special handling, i.e. for which you write your own handlers, instead of using the synthesized ones. That way you can filter access to certain ivars, or even create properties that don't have any backing storage, and are just "aliases" to other properties, e.g. an Angle class that has a degrees property giving the angle in degrees, and a radians property denoting the same angle in radians (this is a simple conversion), or a property that must do a dictionary search to find its value, etc.
In Delphi, which was (AFAICT) one of the first languages with properties as language construct at all, it is customary to wrap ALL ivars in properties (but not all have to be public), and there are many such "unreal" (I am deliberately avoiding the term "virtual" here) properties, i.e. the ones that are only implemented in code, and not just getters and setters for an ivar.
Properties provide encapsulation, abstraction and a degree of protection against certain often made errors, and that is why they are to be preferred over direct access to ivars, IMO.
Addition
It doesn't make sense to declare and implement (either via #synthesize or with custom setters and getters) public properties for each ivar. Only expose publicly what others may need. Internal state can also be exposed to your own code via properties, but that should be done with a private or empty category in the implementation file. That way you get the automatic handling of retain/release and still don't expose them to the public.

Would I ever want to use any #property attributes other than "retain" and "nonatomic" for UI variables?

I'm diving into iOS development and I find that for each of my UI controls, I always just blindly declare their #property like so, since that's how it was done in some tutorial I read when I started learning...
#property (retain, nonatomic) IBOutlet UILabel *lblStatus;
I'm still getting familiar with these attribute types and what they mean, but I find these two attributes allow me to accomplish my goals. Would I ever want to use any #property attributes other than "retain" and "nonatomic" for UI variables?
Thanks in advance for all your help!
NOTE: This answer is more relevant to UI Items in general.
Yes there is other situation where you would want to use the "assign" macro instead of "retain" (Assign is default for now but you get warning at compile-time if you don't specify it explicitly)
Apple gives a good example of this on one of their tutorial: Advanced UITableViewCell
They only "assign" in order to avoid cycle retains. (each of the view retains the other so they can't be deallocated).
NOTE: I missed the reference to UI variables in the question, so this answer is a more general discussion.
Yes, you will definitely need to use other attributes than those two, although that combination is the most common one.
copy - Use this in situations where you don't want as subsequent change to the data to be "picked up" by your class. In other words, when you want full control of the data once it's passed in. Sometimes this is desirable, sometimes not. Classes like NSString and UIColor are often used through properties with the copy attribute. My answer here gives a little bit more background.
assign - You use this with primitive types like int. You can't retain or copy an int or a float, because they are not objects, so you have to use assign. (Also, you don't have to, and can't, release those variables in your dealloc method.) This is true also for C structs, which are not covered by the Objective-C retain count system.
assign special case - sometimes you use assign even with objects, because you want to avoid retain cycles. Look at the header for UITableViewfor example. You'll notice that the delegate property is declared like this: #property(nonatomic, assign) id<UITableViewDelegate> delegate . Delegate properties should always be declared with assign and the same applies in some other situations, although you are not likely to run into them very soon.
nonatomic - This tells the compiler that the property is intended only to be accessed from one thread, and therefore it can omit some code that would otherwise slow down your program (potentially considerably). So the rule here is: if the property will, or might, be accessed from several threads, you should not declare it to be nonatomic (atomic is the default). Note however that making properties atomic is in no way sufficient to make your code thread safe. That's another, and much much thornier, topic.
The answer is NO. The reason behind this is the reason why we are using nonatomic and retain. From memory management guide "Objects in the nib file are created with a retain count of 1 and then autoreleased. As it rebuilds the object hierarchy, UIKit reestablishes connections between the objects using setValue:forKey:, which uses the available setter method or retains the object by default if no setter method is available. This means that (assuming you follow the pattern shown in “Outlets”) any object for which you have an outlet remains valid." So we are providing this setter just to make a match with the default behavior. Yes, it is possible to declare the setter in other ways but at least I have not found no reason to do so. If we use assign instead of retain, then there is no guarantee that the objects will remain valid. And memory management is already critical in iPhone and obviously I don't want to make it further critical by ignoring the convention. -- edit The answer NO is only for UI variables, that is for IBOutlets. Don't be confused. Other attributes are necessary in other cases as explained in other answers.
(retain) is generally used for instance variables and assign will go for delegates and primitive data types like bool , int

Memory Management on the iPhone

I'm sorry to ask such a simple question, but it's a specific question I've not been able to find an answer for.
I'm not a native objective-c programmer, so I apologise if I use any C# terms!
If I define an object in test.h
#interface test : something {
NSString *_testString;
}
Then initialise it in test.m
-(id)init {
_testString = [[NSString alloc] initWithString:#"hello"];
}
Then I understand that I would release it in dealloc, as every init should have a release
-(void)dealloc {
[_testString release];
}
However, what I need clarification on is what happens if in init, I use one of the shortcut methods for object creation, do I still release it in dealloc? Doesn't this break the "one release for one init" rule? e.g.
-(id)init {
_testString = [NSString stringWithString:#"hello"];
}
There is a neat acronym to remember what you have to release
N.A.R.C - new, alloc, retain, copy.
If it's not created with alloc, new, copy, mutableCopy then you're not responsible for releasing it.
This site has some good quick overviews of things like memory management.
Here's a quote from cocoadevcentral:
If you create an object using the
manual alloc style, you need to
release the object later. You should
not manually release an autoreleased
object because your application will
crash if you do.
Just to clarify things a bit. When you get an object through N.A.R.C. as sylvanaar says you do need to release it. In other cases you are getting an autoreleased object that will be released automatically at some later time. That will be bad in the code you presented here, because you do want this string to stay around at least as long as your object. So you actually need to do an explicit retain to keep it alive for your object.
That is not directly answering your question, but rather anticipating the next one ;-)
If you set an attribute with an autorelease, the object in the attribute can die at anytime beyond the immediate scope. Convenience methods i.e. ones that start with a type: string, array, dictionary etc, return autoreleased objects. You only use autoreleased objects when you don't care whether or not they survive beyond the present scope.
What you really need to do in this case is use accessors, either the synthesized or custom, to manage your retention automatically.
If you do:
#property(nonatomic, retain) NSString *_testString; // .h
#synthesize _testString; //.m
then in code use the reference form:
self._testString = [NSString stringWithString:#"hello"];
... then the only place you have to release _testString is in dealloc. The compiler will create synthesized accessors which will automatically manage the properties memory for you.
By the way, you should not use underscores for names. Apple reserves underscore names for itself so you can get a naming collision.
In the first part of the example you do indeed have to have a release for the string somewhere.
In the second part of the example because its an autoreleased you don't need to call the additional release in the dealloc method. This will actually cause a crash as you are attempting to send a message to something that no longer exists...
On the contrary, you need to retain the object you get from stringWithString:. As you correctly noted, you don't own that object and thus don't need to release it. But because you don't own it, it's free to disappear at any time, leaving you with a crash if you're lucky (and a very odd bug if you're not). So you need to retain the object, and then you do need to release it in dealloc.
All of this is explained very well in the memory management guide. I suggest you read it over a couple of times. It's not very long or difficult, and once you internalize it, you'll never have to wonder again.
The rule is if you create an object with new, alloc, copy or you retain it, you need to release it. Objects created in any other way must not be released.
So in your specific case, you would not need to release your string created with stringWithString.
By the way, I would recommend the Cocoa and Objective-C: Up and Running book for learning more about things like this. Great introduction if you are new to Cocoa programming.