clarification about #property attribute - objective-c

In the following example, does stringWithString:(NSString *) copy the memory address/location of theName to name or it actually copies the data from theName to name?
#interface AddressCard:NSObject
-(void)setName:(NSString *)theName;
#end
#implementation AddressCard
NSString *name;
-(void)setName:(NSString *)theName
{
if(name!=theName)
name = [NSString stringWithString:theName];
}
#end
If I change the code to following, what does copy do differently?
#interface AddressCard:NSObject
#property (copy, nonatomic) NSString *name;
#end
#implementation AddressCard
#synthesize name;
#end
In general, does copy (#property attribute) copy the address of the data or copies the data from one variable to another? If it is latter case, are we not consuming a lot of memory when the variable represents large data?
Thank you for your time and response!

+[NSString stringWithString:] will effectively 'copy' the string.
In general, does copy (#property attribute) copy the address of the data or copies the data from one variable to another?
It performs whatever the object considers is a copy. It may return a new object, or it may return itself. For example, +[NSString stringWithString:]could just return the parameter retained and autoreleased if the parameter is already immutable. If the parameter is mutable, then it will return a new instance, so you are guaranteed to have an immutable instance.
If it is latter case, are we not consuming a lot of memory when the variable represents large data?
Aha - but that's the trick! Yes, you could end up making many new allocations with copy, but the trick is often that copies of reference counted objects are truly very shallow in most cases when you favor immutable types and using copy. Many collections types can simply return themselves if they are already immutable, or their ivars may do so, so it's actually a really good idea to ensure you are not passing around mutable objects -- so creating an immutable copy early really allows this optimization to propagate, and saves you a ton of allocations (but not always -- there are a number of corner cases for all these variants).
Note: Not all classes distinguish immutability from mutability, so a copy does not always return an immutable object.

stringWithString will create a copy if it's mutable. But be aware since it's not alloc, init, copy method it's autoreleased. The copy you are now holding will go poof at some point right after that set method exits. If you did initWithString instead, it would create another string as well but retain it.
The copy attribute means the property will be assigned the object returned after sending the copy message to the object that was passed in. That means it's up to that object type to determine how it handles a copy. For your specific string example, (copy) will create a copy of the string back to the caller - a copy that's retained. It's up to the caller to release the retained object. According to the memory guidelines, copy will retain the object.

Related

Is there any real point to the (copy) attribute in a property?

I had assumed that the purpose of the copy attribute was so that I could just assign one property to another (say) and have the underlying getter/setter methods handle everything properly. But having reviewed a number of articles (including some on stackoverflow) it's not clear to me that there's any real benefit over simply using the appropriate methods to copy stuff explicitly. For a start, I discovered that assigning a mutable string to another mutable string still leaves you with a non-mutable string, so what good is that?
Does this work properly for other classes? In other words, in general, if I have
#property (copy) Foo* f1;
#property (copy) Foo* f2;
....
#property (copy) Foo* fn;
can I generally write
f1 = f2
f3 = f2
and get proper copies, i.e. completely independent objects?
(copy) will call the copy method on the item being set, so it will depend on the object. Let's see an example with NSString and see if that helps?
Two classes ObjectWithCopy
#interface ObjectWithCopy : NSObject
#property (copy) NSString *aString;
#end
and ObjectWithoutCopy
#interface ObjectWithoutCopy : NSObject
#property (strong) NSString *aString;
#end
Pretty easy so far, and we all know NSString is immutable, so what will "copy" do? Well remember NSMutableString is a subclass of NSString. So we could pass that in to the setter instead. What happens when we do this?
NSMutableString *aMutableString = [[NSMutableString alloc] initWithString:#"Hello World"];
ObjectWithCopy *objectWithCopy = [[ObjectWithCopy alloc] init];
objectWithCopy.aString = aMutableString;
NSLog(#"ObjectWithCopy.aString = %#", objectWithCopy.aString);
//Now we change aMutableString
[aMutableString appendString:#" and every other world"];
NSLog(#"ObjectWithCopy.aString after aMutableString was modified = %#", objectWithCopy.aString);
NSLog(#"Now what happens without copy?");
// Reset aMutableString
aMutableString = [[NSMutableString alloc] initWithString:#"Hello World"];
ObjectWithoutCopy *objectWithoutCopy = [[ObjectWithoutCopy alloc] init];
objectWithoutCopy.aString = aMutableString;
NSLog(#"ObjectWithoutCopy.aString = %#", objectWithoutCopy.aString);
//Now we change aMutableString and see what objectWithoutCopy.aString is?
[aMutableString appendString:#" and every other world"];
NSLog(#"ObjectWithoutCopy.aString after aMutableString was modified = %#", objectWithoutCopy.aString);
The output?
2014-02-02 10:40:04.247 TableViewCellWithAutoLayout[95954:a0b] ObjectWithCopy.aString = Hello World
2014-02-02 10:40:04.248 TableViewCellWithAutoLayout[95954:a0b] ObjectWithCopy.aString after aMutableString was modified = Hello World
2014-02-02 10:40:04.248 TableViewCellWithAutoLayout[95954:a0b] Now what happens without copy?
2014-02-02 10:40:04.248 TableViewCellWithAutoLayout[95954:a0b] ObjectWithoutCopy.aString = Hello World
2014-02-02 10:40:04.249 TableViewCellWithAutoLayout[95954:a0b] ObjectWithoutCopy.aString after aMutableString was modified = Hello World and every other world
Whoa - our immutable string was changed on ObjectWithoutCopy!?!? That's because it really was a NSMutableString after all and without copy we are simply pointing to whatever was passed in. So any changes that occurred with that passed in object will be seen in both the class and the function variable. That is why it's so often suggested that when you have an NSString property you use (copy), you don't expect an NSString to change.
Copy makes the assign statement this _aString = [passedInString copy];. As some have pointed out can do anything so long as it conforms to the NSCopying protocol, but should create an independent copy of the object to make sure change the outside world makes doesn't affect your class. So someone could create a subclass of NSString (which you probably should never do) that overrides copy to do nothing and you could still see your NSString change out from under you, but in general it's a pretty safe bet that NSCopying was done correctly. At least that's the best you can really do.
Edit 1:
As #David mentions in his comment (and is maybe his real question?), [aMutableString copy] actually returns a object of type NSString. I completely agree this is confusing. If I was making NSMutableString I would have copy return a NSMutableString. Actually I think the real WTF here is that Apple has created a mutable subclass of a non-mutable class. In C#/Java, you don't have a mutable string, instead you use another class called StringBuilder.
So if this is so confusing, why do so many people use copy on NSString properties? Because it most likely does what you actually want it to. If your class has an NSString property, you picked that because you don't want to worry about the string changing out from under you. To do that you really want a copy of the string passed in. And if it's a NSMutableString you probably want an NSString copy because you don't want to give that mutable string out and have it changed out from under you. If copy on a NSMutableString returned an NSMutableString I don't think people would use the copy attribute, but create a custom setter that set _aString = [[NSString alloc] initWithString: inputString]. This is probably clearer, and if you think it is that it is maybe what you should do. But at this point it's convention to use copy on NSString properties, so I'll probably continue to use it. You may or may not agree with it, but your question is why do people use copy then this is why I do personally.
Edit 2:
#David asks why doesn't copy work this way? "If I copy a string then I want a subsequent call to be able to change it." I think if you really want the side effects you probably should be declaring an NSMutableString without the copy modifier (you probably should never use copy and NSMutableString, but create your own setter).
I really can't think of a reason in my nearly 15 years of programming why I would not want the person setting the string's side effect but I would want any old person who get's the string's side effect. That's really weird.
Further I can't for the life of me think of why I would want that situation but advertise it as an NSString instead. I mean why? Why would want for your immutable property to be sometimes mutable, but only when the setter (which you don't control) tells you too but you don't want the side effects from from object that was set with. AND you don't tell any one about it and they have to just figure it out? My head hurts.
My guess is this is why Apple did what it did. But it's only a guess.
Further, if you can get away with an immutable data type you should. It reduces all sorts of complexity especially with multithreading.
Of course Objective-C (and most OOP languages) let you do all of this if you really really want to. That's up to you programmer and your team. You can also test the accelerometer by bashing your phone against your skull. I don't think Apple recommends either approach though.
Yes, you get completely independent objects. What else would the copy attribute do?
I think that the copy specifier creates a new instance of an object if it is necessary. For example if the object is mutable (object passed to the setter of course). If not it usually just retains it.
Consider that copy means that the instance is logically copied. The way it is implemented (memory copied or just extra retain) does not matter that much actually.
The copy specifier just means that the -copy method of the object in question will be called during assignment (see: the NSCopying protocol). This method's purpose is usually to return a "completely independent object" so that's usually what you'll get. There are exceptions though.
For instance, if your object is an immutable value (NSString being the canonical example), then there's no reason to -copy it to get an "independent object". So in that case, as an optimization, -copy only results in a retain, not a new object.
Of course, any custom class or subclass can override -copy or -copyWithZone: to do any number of unpredictable, destructive things. But the convention is to return, as you say, an "independent object" — or self in contexts where "independent" doesn't mean anything.

Are Mutable classes "heavier?"

On some intuitive (perhaps wrong) idea of performance, I always get a copy of a mutable instance before I store it. So if a property expects an NSArray I take the mutable array I'm working with and store it as self.array = mutableArray.copy (though the property is specified as strong or retain).
This seems silly to me, suddenly, but is it? Do mutable instances -- doing the exact same task -- perform the same?
Note: The mutable instance falls out of scope and (thanks to ARC) gets released right after this, so there's no worry that it'll be mutated once it's assigned to the property.
NSArray and NSMutableArray are both (as far as I'm aware) implemented on top of CFArray, which simply has a flag specifying whether it's mutable. CFArray functions which require a mutable array have an assertion right at the beginning, checking that flag:
void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) {
// snip...
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
Mutable and immutable CFArrays are identical other than passing or failing this assertion, and so should NSArrays and NSMutableArrays be, performance- or other-wise.
Partly answered here: NSArray size and mutability
NSMutableArray is not noticeably slower or larger (memory-wise) than an NSArray. It's basically just an NSArray that reallocates itself when it gets full as as bigger array, and keeps doing that as you add items to it.
The reason for copying mutable arrays as immutable ones when assigning them to values in your class is so you can guarantee that their values don't change. If you store a mutable array in your class, other code can change its values outside of your class without calling any of your methods. That leaves you vulnerable to crashes due to internal inconstancy errors within your classes.
For example, supposing that when the array was set, you cached the length of the array as an int property in your class. That would be fine if the array was immutable, but if it was mutable, someone else could change the array, and your cached value would now be wrong, but you have no way of knowing that.
However, it's not necessary to do the copying manually. If you declare your array properties as:
#property (nonatomic, copy) NSArray *foo;
Then whenever you assign an array to object.foo, it will automatically be copied. You don't need to copy it again yourself. It's best practice to use a property type of copy instead of strong/retain for any type that has a mutable variant, like so:
#property (nonatomic, copy) NSArray *foo;
#property (nonatomic, copy) NSString *foo;
#property (nonatomic, copy) NSDictionary *foo;
#property (nonatomic, copy) NSData *foo;
etc...
However be careful not to use it for mutable properties, or it will make an immutable copy stored in a property that thinks it's mutable and cause a crash if you try to mutate it. The synthesised copy property isn't smart enough to use mutableCopy automatically.
#property (nonatomic, copy) NSMutableArray *foo; //don't do this
For clarity you're asking if, given an NSArray and an NSMutableArray both subjected to a battery of non-mutating test methods, does the NSArray perform noticeably faster? I specify non-mutataing, because it looks like you're copying a mutable array to an immutable array with the belief that the immutable array will perform its non-mutating methods faster than the mutable array. Anyways, the answer is no. (But don't take my word for it; profile).
Even if NSMutableArray overrode some non-mutating methods (which we can't know about, one way or another), you wouldn't need to worry about it. Adding a couple CPU cycles is trivial compared to the overall computational complexity of the operation. As long as NSMutableArray doesn't manage to turn a O(n) lookup-operation into a O(n2) operation, you'll be fine 99% of the time. (Those complexities are just fictitious examples).
While there are perfectly valid reasons why you might want to copy a mutable array into an immutable array (as pointed out by #NickLockwood), performance shouldn't be one of them. Premature optimization is very bad, after all.

NSString retain copy question

I've seen a few posts on here about the issue of using retain or copy for strings. I still can't quite get my head around the difference or the importance.
In my case at the moment I have a class with a whole load of nsstrings to hold strings.
I want this class to only be instantiated once and I want its nsstring variables to change depending on the index clicked in a table view.
Would I be correct in saying that if I chose to use retain that my nsstrings would be overwritten each time I set their value on my tableview click and that if I chose copy I would somehow have 2 instances of each string....?
I'm sorry ..... I totally don't get it
This is a question about copying mutable objects vs. immutable ones. Since NSString objects are immutable (you cannot change their contents), they implement -copy like this:
- (id) copyWithZone: (NSZone *) zone
{
return [self retain];
}
If you think about it, there's no reason to duplicate an immutable object because that's a waste of memory. On the other hand, NSMutableString objects can see their contents change during their lifetime, so if you request a copy of an NSMutableString, you will get a real copy, a different object.
If your strings are not NSMutableStrings, it does not matter whether you retain or copy them. However, choosing the right method is important if you later refactor your code to use NSMutableStrings. A common logic should answer the following question for you: if I get an object whose contents may change outside, which value do I need? More often than not you will want to make a copy.

Pointers, primitives, and properties in Objective-C classes

I really need some clarification — I have a few questions and I'm all mixed up right now.
Here is a simple class interface:
#import <UIKit/UIKit.h>
#interface Car : NSObject{
NSInteger carID;
NSString *carName;
}
#property (nonatomic, assign) NSInteger carID;
#property (nonatomic, copy) NSString * carName;
#end
Why is carID not declared as a pointer?
Why does it use "assign" for carID instead of "copy"?
Why even declare class members as pointers in the first place? (In my main program, my Car object will be used as a pointer.)
NSInteger is simply a typedef for a primitive type (int on 32-bit, long on 64-bit) — it is not an object, and can as such not be retained or copied.
Class members are always pointers; you never pass the "real" objects around; as that would be, at best, unmanageable.
Edit: To expand on the last paragraph: Objective-C class instances always exist on the heap, never on the stack; this is to facilitate things like reference counting and self-managed object life cycle.
This also means that it's very hard to accidentally copy an object; but on the flip side it can be somewhat easier to accidentally dispose of an object you still need. Still, the latter is more readily debugged (as it causes a nice, big crash (at best, anyway)) than the last (which at worst causes a slow leak).
The property for carID is not really correct. For types that are not pointers, the correct definition looks like:
#property (nonatomic) NSInteger carID;
It's always going to be copying a value anyway, but "copy" has a very different meaning in properties - for objects it's going to call [object copy] when that property is used to set a new value.
Or you could drop off the nonatomic, but then the property is more expensive to call (by some small amount). Just leave in the nonatomic unless you have a good reason not to.
Thanks guys!
So in Objective-C , you have int and Pointer Int.
How do you declare these in objective C
-int being a regular int.
-Pointer Int being an object representation of an integer. Since it is an object, it can also point to pointers*. Right?
And Pointer Int pointers can point to pointers of any type If I wanted to. Right?
It will cause a crash if it doesn't point to a Pointer int. But it will compile successfully, Right?
But in what scenarios would I prefer using a regular int to a Pointer Int?
I would like to add some clarification why you would want to use:
#property (nonatomic, copy) NSString * carName;
instead of
#property (nonatomic, retain) NSString * carName;
The copy keyword implies language semantics that you want to have a COPY of the NSString passed into your current object reference. So the pointer does not change (that is why you don't have to release the object ref).
The retain keyword makes it so that you get the pointer which will be retained because the pointer reference changes for this data member (and the current one will be released). Copying a NSString might not be a considerably heavy operation, so copying NSString is used often. You have to be careful what type of property you declare as copy. There might be a considerable amount of effort to produce a copy of types like Dictionaries etc (see shallow, deep copy etc).
Hope that helps!

NSString property: copy or retain?

Let's say I have a class called SomeClass with a string property name:
#interface SomeClass : NSObject
{
NSString* name;
}
#property (nonatomic, retain) NSString* name;
#end
I understand that name may be assigned a NSMutableString in which case this may lead to errant behavior.
For strings in general, is it always a good idea to use the copy attribute instead of retain?
Is a "copied" property in any way less efficient than such a "retain-ed" property?
For attributes whose type is an immutable value class that conforms to the NSCopying protocol, you almost always should specify copy in your #property declaration. Specifying retain is something you almost never want in such a situation.
Here's why you want to do that:
NSMutableString *someName = [NSMutableString stringWithString:#"Chris"];
Person *p = [[[Person alloc] init] autorelease];
p.name = someName;
[someName setString:#"Debajit"];
The current value of the Person.name property will be different depending on whether the property is declared retain or copy — it will be #"Debajit" if the property is marked retain, but #"Chris" if the property is marked copy.
Since in almost all cases you want to prevent mutating an object's attributes behind its back, you should mark the properties representing them copy. (And if you write the setter yourself instead of using #synthesize you should remember to actually use copy instead of retain in it.)
Copy should be used for NSString. If it's Mutable, then it gets copied. If it's not, then it just gets retained. Exactly the semantics that you want in an app (let the type do what's best).
For strings in general, is it always a good idea to use the copy attribute instead of retain?
Yes - in general always use the copy attribute.
This is because your NSString property can be passed an NSString instance or an NSMutableString instance, and therefore we can not really determine if the value being passed is an immutable or mutable object.
Is a "copied" property in any way less efficient than such a "retain-ed" property?
If your property is being passed an NSString instance, the answer is "No" - copying is not less efficient than retain.
(It's not less efficient because the NSString is smart enough to not actually perform a copy.)
If your property is passed an NSMutableString instance then the answer is "Yes" - copying is less efficient than retain.
(It's less efficient because an actual memory allocation and copy must occur, but this is probably a desirable thing.)
Generally speaking a "copied" property has the potential to be less efficient - however through the use of the NSCopying protocol, it's possible to implement a class which is "just as efficient" to copy as it is to retain. NSString instances are an example of this.
Generally (not just for NSString), when should I use "copy" instead of "retain"?
You should always use copy when you don't want the internal state of the property changing without warning. Even for immutable objects - properly written immutable objects will handle copy efficiently (see next section regarding immutability and NSCopying).
There may be performance reasons to retain objects, but it comes with a maintenance overhead - you must manage the possibility of the internal state changing outside your code. As they say - optimize last.
But, I wrote my class to be immutable - can't I just "retain" it?
No - use copy. If your class is really immutable then it's best practice to implement the NSCopying protocol to make your class return itself when copy is used. If you do this:
Other users of your class will gain the performance benefits when they use copy.
The copy annotation makes your own code more maintainable - the copy annotation indicates that you really don't need to worry about this object changing state elsewhere.
I try to follow this simple rule:
Do I want to hold on to the value of the object at the point in time when I am assigning it to my property? Use copy.
Do I want to hold on to the object and I don't care what its internal values currently are or will be in the future? Use strong (retain).
To illustrate: Do I want to hold on to the name "Lisa Miller" (copy) or to I want to hold on to the person Lisa Miller (strong)? Her name might later change to "Lisa Smith", but she will still be the same person.
Through this example copy and retain can be explained like:
NSMutableString *someName = [NSMutableString stringWithString:#"Chris"];
Person *p = [[[Person alloc] init] autorelease];
p.name = someName;
[someName setString:#"Debajit"];
if the property is of type copy then ,
a new copy will be created for the [Person name] string that will hold the contents of someName string. Now any operation on someName string will have no effect on [Person name].
[Person name] and someName strings will have different memory addresses.
But in case of retain,
both the [Person name] will hold the same memory address as of somename string, just the retain count of somename string will be incremented by 1.
So any change in somename string will be reflected in [Person name] string.
Surely putting 'copy' on a property declaration flies in the face of using an object-oriented environment where objects on the heap are passed by reference - one of the benefits you get here is that, when changing an object, all references to that object see the latest changes. A lot of languages supply 'ref' or similar keywords to allow value types (i.e. structures on the stack) to benefit from the same behaviour. Personally, I'd use copy sparingly, and if I felt that a property value should be protected from changes made to the object it was assigned from, I could call that object's copy method during the assignment, e.g.:
p.name = [someName copy];
Of course, when designing the object that contains that property, only you will know whether the design benefits from a pattern where assignments take copies - Cocoawithlove.com has the following to say:
"You should use a copy accessor when the setter parameter may be mutable but you can't have the internal state of a property changing without warning" - so the judgement as to whether you can stand the value to change unexpectedly is all your own. Imagine this scenario:
//person object has details of an individual you're assigning to a contact list.
Contact *contact = [[[Contact alloc] init] autorelease];
contact.name = person.name;
//person changes name
[[person name] setString:#"new name"];
//now both person.name and contact.name are in sync.
In this case, without using copy, our contact object takes the new value automatically; if we did use it, though, we'd have to manually make sure that changes were detected and synced. In this case, retain semantics might be desirable; in another, copy might be more appropriate.
#interface TTItem : NSObject
#property (nonatomic, copy) NSString *name;
#end
{
TTItem *item = [[TTItem alloc] init];
NSString *test1 = [NSString stringWithFormat:#"%d / %#", 1, #"Go go go"];
item.name = test1;
NSLog(#"-item.name: point = %p, content = %#; test1 = %p", item.name, item.name, test1);
test1 = [NSString stringWithFormat:#"%d / %#", 2, #"Back back back"];
NSLog(#"+item.name: point = %p, content = %#, test1 = %p", item.name, item.name, test1);
}
Log:
-item.name: point = 0x9a805a0, content = 1 / Go go go; test1 = 0x9a805a0
+item.name: point = 0x9a805a0, content = 1 / Go go go, test1 = 0x9a84660
You should use copy all the time to declare NSString property
#property (nonatomic, copy) NSString* name;
You should read these for more information on whether it returns immutable string (in case mutable string was passed) or returns a retained string (in case immutable string was passed)
NSCopying Protocol Reference
Implement NSCopying by retaining the original instead of creating a
new copy when the class and its contents are immutable
Value Objects
So, for our immutable version, we can just do this:
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
Since name is a (immutable) NSString, copy or retain makes no difference if you set another NSString to name. In another word, copy behaves just like retain, increasing the reference count by one. I think that is an automatic optimization for immutable classes, since they are immutable and of no need to be cloned. But when a NSMutalbeString mstr is set to name, the content of mstr will be copied for the sake of correctness.
If the string is very large then copy will affect performance and two copies of the large string will use more memory.