What exactly is the difference between retain and copy? what is its significance on reference counting?
I know that when an object is allocated using alloc/retain, reference count goes up by one.
so how about using copy?
Another question relating to this is, the difference between using
#property(nonatomic, retain) and #property(nonatomic,copy)?
retain -- is done on the created object, it just increase the reference count.
copy -- create a new object
Answering your question to the best of my knowledge.
First, What exactly is the difference between retain and copy? what is its significance on reference counting?
retain - "Specifies that retain should be invoked on the object upon assignment. ... The previous value is sent a release message." So you can imagine assigning an NSString instance (which is an object and which you probably want to retain). So the retain count goes up by 1.
copy - "Specifies that a copy of the object should be used for assignment. ... The previous value is sent a release message." Basically same as retain, but sending -copy rather than -retain. if i remember correctly the count will go up by 1 too.
ok, now going into more detail.
Property attributes are special keywords to tell compiler how to generate the getters and setters. Here you specify two property attributes: nonatomic, which tells the compiler not to worry about multithreading, and retain, which tells the compiler to retain the passed-in variable before setting the instance variable.
In other situations, you might want to use the “assign” property attribute instead of retain, which tells the compiler NOT! to retain the passed-in variable. Or perhaps the “copy” property attribute, which makes a copy of the passed-in variable before setting.
I hope that helps. I found another post in here that might help you too.
Objective C - Assign, Copy, Retain
Cheers!
Jose
Generally speaking, copy creates a new object which has the same value with the original object, and sets the reference count of the new created object to 1 (By the way, reference count of the original object is not affected).
However, copy is equivalent to retain for immutable object, which JUST increate the reference count of the original object by 1.
Related
Suppose I have an object, for example an NSString, with retain count 5. When I call copy on it, I get a new copy of the object; does this new object have the retain count of its original object ?
It depends. copy is a convenience method for copyWithZone:,
and the "NSCopying Protocol Reference" states:
Your options for implementing this protocol are as follows:
Implement NSCopying using alloc and init... in classes that don’t
inherit copyWithZone:.
Implement NSCopying by invoking the
superclass’s copyWithZone: when NSCopying behavior is inherited. If
the superclass implementation might use the NSCopyObject function,
make explicit assignments to pointer instance variables for retained
objects.
Implement NSCopying by retaining the original instead of
creating a new copy when the class and its contents are immutable.
(I have modified the following two statements after all that feedback.)
For example, NSString is an immutable object, and copy just retains the object
and returns a pointer to the same object. Retaining the object might increase the
retain count, but not necessarily (as in the case of string literals.)
Copying an NSMutableString would probably create a new object and return that.
The new object would have its own retain count independent of the original object.
But you should not care about the difference. With manual reference counting,
copy returns an object that you own and have to release eventually.
With ARC, the compiler with automatically handle that.
copy returns an object that is a semantic [shallow] copy(1) of the object. What the copy method returns is an implementation detail; it may return the same object, it may return a different instance of the same class, or it might even return an instance of a different class.
Doesn't matter.
What matters is that the returned object, under manual retain/release, has a retain count of +1. Not 1, but +1. It might actually be 1, 42, 981, or -1. Doesn't matter.
All that matters is that you must balance that retain with a release or autorelease somewhere if you want to relinquish the object back to the system. Which may not actually cause it to be deallocated; that is an implementation detail of no concern (until optimization time, anyway).
(1) semantic [shallow] copy means that the object returned is an effective shallow copy. The state contained within the copied object (but not within objects contained within the object -- that is the shallow part) will not change when the original object changes state. For a mutable object, copy must actually create a new instance of some object -- most likely an immutable variant class -- that can contain the original state.
For an immutable object, the copy method might be simply implemented as return [self retain];. Or, in the case of static NSStrings (NSCFStrings), it might simply be return self; as retain/release/autorelease are no-ops on such strings.
No, a copied object will have a retain count of 1, just like a newly initialized object.
I highly recommend you read the Memory Management Guide if you wish to learn more.
If you're new to iOS development, the iOS App Programming Guide should be read first, and is a great use of your time.
I just noticed you didn't tag this as iOS specific, if you're coding for Mac, the Programming with Objective-C guide might be more appropriate for you.
To really get your head around this issue, don't think in terms of retain count, think in terms of pointer ownership (like ARC does).
If an object has a "retain count" of 5, that means five pieces of code somewhere are each holding a (strong) pointer to its memory address. If you copy that object, you get a pointer to the address of the new, copied object. The other five pieces of code are still pointing to the original object. There's only one piece of code pointing to the new object, so its "retain count" is one.
As noted in other answers, the Memory Management Guide definitely helps make this all clear.
Why did I put "retain count" in quotes? Because it's only useful as a general concept -- you shouldn't be using retainCount directly, or you'll hear from #bbum.
Objective-C plays some clever tricks when you ask it to copy objects, and as a result retain counts might not be what you think they should be.
Let's say you have an object pointer x with a retain count of n, and call the copy method which returns an object pointer y.
NSObject* x = ...;
NSObject* y = [x copy];
Then the rule is that if you release x n times, and release y once, all objects will be gone. Usually this is achieved by leaving x unchanged, and giving y a retain count of 1.
However, if x points to an immutable object, then Objective-C may decide that no copy needs to be done. The result is that y = x. Still, the rule above still applies: Releasing x n times and y once (even though they are the same object) will free all the objects involved. That's achieved by the copy method returning x with a +1 retain count.
Copy on mutable object like NSMutableArray will create a new copy and retain count will be 1 while copy immutable object like NSArray will point to same reference and increase the retain count by 1.
I am using the 'analyze' tool in xcode to check for potential leakages in my app.
I am getting the following warning as a result.
How do I resolve the potential leak shown above? "self.answerArray" is just an array I declared in my header file
You've called mutableCopy on the array (which returns a new array with a retain count of +1 - You own it), and you assign it to a property (which I assume is a strong/retain property) and you're not releasing it. You're leaking the memory.
You should release tempArray after assigning it to the property - and ensure the property is released in your class' dealloc method.
You should either send retain/release to answerArray (release old object before assigning a new one, retain the new object), or, probably better, declare a property
#property (retain) NSArray* answerArray;
this way compiler will generate release/retain (on assign) for you. See documentation. Otherwise the object answerArray was referencing before the assignment (answerArray = tempArray) will remain dangling in memory.
In case you will use a declared property, make sure to add your temp variable to autorelease pool:
tempArray = [[self.answerArray mutableCopy]autorelease];
or just send it release yourself (right before it goes out of scope).
Isn't it unnecessary to retain a static variable since it stays around for the duration of the program, no matter if you release it?
See this code:
https://github.com/magicalpanda/MagicalRecord/blob/master/Source/Categories/NSManagedObjectContext+MagicalRecord.m#L24-29
I'm assuming you mean a static object pointer, such as static NSString *foobar;.
Such variables indeed have a lifetime as long as the application, but the variables we're talking about are pointers only. In Objective-C, objects are always dynamically allocated, and so we always address them with a pointer to their type, but the underlying data for an object is still present out in the dynamically allocated wild blue yonder.
You must still retain the object because, while the pointer to the object will never go out of scope, the object itself can be deallocated just like any other object, and so your pointer will end up pointing to garbage, or worse, another unrelated object.
A simplified version of Jonathan Grynspan's accepted answer:
The retain isn't for the variable which points to an object. That variable will last forever because it's static. The retain is for the object the variable points to. Without the retain the object could (and should) be deallocated. Then you've got a variable pointing to a thing which will cause a sigabrt. This variable pointing nowhere is known as a "dangling pointer."
For the ARC context, the best thing to do is declare the static variable as strong, so something like this:
static ThatClass * __strong thatStaticVariable;
This ensures that the object that thatStaticVariable points to will be a valid object (i.e., never gets deallocated) once assigned. However, you don't actually need the __strong keyword at all, because it's the default (so sayeth the docs, thanks to #zpasternack), so just use
static ThatClass *thatStaticVariable;
and you're good.
Note: forever = while the application is running
When to use attributes and What is the purpose of each attribute?
Some attributes:
readonly - use if you don't want a setter
retain - use if you want values assigned to your property to be retained
copy - use if you want values assigned to your property to be copied.
assign - use if you want new values to be assigned with no retain or copy.
nonatomic - use to disable the mechanism that makes property access atomic. An atomic property is guaranteed to give you a pointer to a real object that still exists or nil. In a multithreaded environment, a nonatomic property could give you an object that has already been deallocated.
What is the difference between copy and retain for NSString?
- (void)setString:(NSString*)newString
{
string = [newString copy];
}
In a general setting, retaining an object will increase its retain count by one. This will help keep the object in memory and prevent it from being blown away. What this means is that if you only hold a retained version of it, you share that copy with whomever passed it to you.
Copying an object, however you do it, should create another object with duplicate values. Think of this as a clone. You do NOT share the clone with whomever passed it to you.
When dealing with NSStrings in particular, you may not be able to assume that whoever is giving you an NSString is truly giving you an NSString. Someone could be handing you a subclass (NSMutableString, in this case) which means that they could potentially modify the values under the covers. If your application depends on the value passed in, and someone changes it on you, you can run into trouble.
Retaining and copying are two different things, the first
is conceptually call-by-reference while the second is call-by-value.
retain : It is done on the created object, and it just increase the reference count.
copy -- It creates a new object and when new object is created retain count will be 1.
Hope This Help for U...:)
Its an old post but here's my view on the question
Retain increases the retain count of an object by 1 and takes ownership of an object.
Whereas copy will copy the data present in the memory location and will assign it to the variable so in the case of copy you are first copying the data from a location assign it to the variable which increases the retain count.
Just remember that retain works on reference and copy works on value
if you use retain, it copy the pointer value from original one.retain also increment the reference count by one.
but in case of copy, it duplicate the data referenced by the pointer and assign it to copy's instance variable.
The biggest difference is that if you use copy, the object you are copying must implement the NSCopying protocol (very easy to do). Not every object implements that, so you need to use care you know for sure what type you'll be operating against (or check for support of that protocol) when trying to call copy.
The best rule of thumb to using copy I can think of, is to always set NSString properties to "copy" instead of retain. That way you get more accurate readings from the Leaks instrument if you mess up and forget to release a string an object is holding onto. Other uses of copy need to be more carefully thought out.
Retaining an object means the retain count increases by one. This means the instance of the object will be kept in memory until it’s retain count drops to zero. The property will store a reference to this instance and will share the same instance with anyone else who retained it too. Copy means the object will be cloned with duplicate values. It is not shared with any one else.
copy: creates a new instance that's a copy of the receiver. It means that you'll have 2 different
retain: Increases the retainCount of the receiver. An object is removed from memory - (with dealloc), when retainCount is 0.
retain attribute is specified such that it can retain the another memory i.e it can be made to point to another address also
copy First copies the address and then retains it.