Setting WEAK to a non #property variable - objective-c

Will need someone with knowledge of ARC to help me.
Basically, I have declared some variables as such in my class
#interface Class{
NSString* one;
NSString* two;
}
#property(nonatomic,weak) NSString* one;
As you can see, I can set the weak identifier to NSString* one. However, I do not need a getter/setter/synthesizer for NSString* two as it is just a common variable. How can I set a weak label to it so the memory is deallocated? Or is automatically set?

You can do it like this:
__weak NSString *two;
But you probably do not want to do it in this case.
Declaring an instance variable __weak means that the reference to the target object (a string in your case) will exist only as long as some other object holds a reference. When the last object holding a strong reference releases the string, your variable two will get nil-ed out automatically. This is very useful when objects hold references to each other, such as in parent-child hierarchies. Since your NSString *two could not possibly hold a reference to your object, using the __weak reference for it is highly questionable.

You can do this without worrying:
NSString* two = [[NSString alloc] init];
When your instance of the class Class is release for some reason, since is the only one (in theory) referencing two, it will be deallocated.

My advice (and I think Apple's although I could be wrong) would be to get into the habit of always using properties for your iVars, then this problem goes away.

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.

Basic Objective-C memory management syntax

I have a property defined like this:
#property (nonatomic, retain) MyClass *someObject;
I'm currently using this assignment statement:
someObject = [[MyClass alloc] init];
In terms of memory managment is the above assignment statement equivalent to:
self.someObject = [[[MyClass alloc] init] autorelease];
Assume #synthesize someObject; is in the #implementation section. Also I'm not using ARC.
Note: The following is based on the EDITED version of the original post, where "assign" has been replaced with "retain" ---
Yes, the two are "equivalent", in that they will both result in leaving the MyClass object (properly) retained with a retain count of 1 in the property. The second version goes through some extra work, which may or may not be an issue, depending on how performance-sensitive you are.
Some people argue you should never use the property reference (ie, self.propname) from within the class, but instead reference the instance variable, especially for initialization and deallocation. Others argue just the opposite. I generally favor always using the property reference, except during initialization where (as in this case) using it might result in an extraneous retain/autorelease.

NSDictionary + ARC + copy vs reference

These are probably are pretty simple YES|NO type questions.
I have some NSDictionaries containing other NSDictionaries. Let's say NSDictionary_A and NSDictionary_B. These persist for the life of the app.
The NSDictionaries contained in NSDictionary_A are passed by reference to various objects:
track.instrument = [NSDictionary_A objectForKey:#"Blue"];
Later it gets changed:
track.instrument = [NSDictionary_A objectForKey:#"Red"];
So first question: The #property instrument is synthesized + retained as strong so does the setter for instrumentset the current value of instrument to nil before setting the new value, and if so, does this affect the source of the reference in NSDictionary_A - in other words, set the reference to nil'? Sounds wrong just writing it out.. so I think the answer is NO here. Also, it probably doesn't matter that the #property instrument is stored as weak or strong since the reference in NSDictionary_A1 persists for the app life but since it is a pointer, should be weak - YES?
Second question: An NSDictionary in NSDictionary_B is passed to an object but it can change some of the values in that NSDictionary:
track.playbackType = [NSDictionary_B objectForKey:#"Random"];
[track.playbackType objectForKey:#"maxRange"] = 20;
So should I be making a copy of the NSDictionary here because it's values will be changed or am I completely misunderstanding this whole reference passing thang?
You are getting mixed up in how pointers work.
For the first question, "track.instrument" is just a pointer. So it will start as "pointing to nil".
this:
track.instrument = [NSDictionary_A objectForKey:#"Blue"];
means, "stop pointing to nil and point to that object"
If you can ensure your dictionary will persist for the entire app then it doesnt matter, whatever is at #blue key will never get dealocated. But for the sake of having the correct code, it should be weak.
Edit: Had read the second question incorrectly.
Second question:
about this:
track.playbackType = [NSDictionary_B objectForKey:#"Random"];
first your pointer points to the NSDictionary from the dictionary.
[track.playbackType objectForKey:#"maxRange"] = 20;
Since it is a NSDictionary this is not valid. You cannot change NSDictionaries because they are immutable, it SHOULD be NSMutableDictionary.
HOWEVER if you are not interested in putting back the modified version into the original dictionary then you can copy it but as a NSMutableDictionary first, and then change it.
NSMutableDictionary *mutableDict = [[NSDictionary_B objectForKey:#"Random"] mutableCopy];
track.playbackType = mutableDict; //Note how track.playbackType has to be NSMutableDictionary aswell.
VERY IMPORTANT: Since you are creating a "new" dictionary. track.playbackType has to be strong, or it will simply get instantly dealocated after the function ends and mutableDict gets out of scope.
References are just pointers, setting one to nil will have no effect except in the following case: It is the last strong reference and other weak references still exist. In that case all the weak references will become nil. Strong properties will set the old value to nil, in effect sending a release call but this affects the REFERENCE, not the CONTENT of the reference.
As for the second question, it is quite confusing and I need more info about playbackType. You say it is an NSDictionary but NSDictionary doesn't have the property maxRange so it must be a type that you defined. You can't change the values of an NSDictionary either because it is immutable.
But here is a generic answer: If you pass a pointer to a mutable object as strong (or weak even) you will be able to change the content of the original. If you pass a pointer to a mutable object as a copy you will get a new object that doesn't affect the original.

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.

Object allocate and init in Objective C

What is the difference between the following 2 ways to allocate and init an object?
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
and
self.aController= [[AController alloc] init];
Most of the apple example use the first method. Why would you allocate, init and object and then release immediately?
Every object has a reference count. When it goes to 0, the object is deallocated.
Assuming the property was declared as #property (retain):
Your first example, line by line:
The object is created by alloc, it has a reference count of 1.
The object is handed over to self's setAController: method, which sends it a retain message (because the method doesn't know where the object is coming from), incrementing its reference count to 2.
The calling code no longer needs the object itself, so it calls release, decrementing the reference count to 1.
Your second example basically does steps 1 and 2 but not 3, so at the end the object's reference count is 2.
The rule is that if you create an object, you are responsible for releasing it when you're done with it. In your example, the code is done with tempAController after it sets the property. It is the setter method's responsibility to call retain if it needs that object to stick around.
It's important to remember that self.property = foo; in Objective-C is really just shorthand for [self setProperty:foo]; and that the setProperty: method is going to be retaining or copying objects as needed.
If the property was declared #property (copy), then the object would have been copied instead of retained. In the first example, the original object would be released right away; in the second example, the original object's reference count would be 1 even though it should be 0. So you would still want to write your code the same way.
If the property was declared #property (assign), then self isn't claiming ownership of the object, and somebody else needs to retain it. In this case, the first example would be incorrect. These sorts of properties are rare, usually only used for object delegates.
As others have noted, the two code snippets you show are not equivalent (for memory management reasons).
As to why the former is chosen over the latter:
The correct formulation of the latter would be
self.aController= [[[AController alloc] init] autorelease];
Compared with the former, this adds additional overhead through use of the autorelease pool, and in some circumstances will lead to the lifetime of the object being unnecessarily extended (until the autorelease pool is released) which will increase your application's memory footprint.
The other "possible" implementation (depending on where the example is from) is simply:
aController = [[AController alloc] init];
However, setting an instance variable directly is strongly discouraged anywhere other than in an init or dealloc method. Elsewhere you should always use accessor methods.
This brings us then to the implementation shown in sample code:
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
This follows best practice since:
It avoids autorelease;
It makes the memory management semantics immediately clear;
It uses an accessor method to set the instance variable.
Note also that your desire to cut the code down to one line is why many people use Autorelease:
self.aController = [[[AController alloc] init] autorelease];
Though in theory on the iPhone autorelease is somehow more expensive (never heard a clear explanation why) and thus you may want to explicitly release right after you assign the object elsewhere.
If you're using Xcode, it can help you detect such code with the static analyzer.
Just hit Build >> Build and Analyze
This will show you a very helpful message at such pieces of code.
One other thing to note is that your example depends on the #property definition of aController also.
If it were defined as #property (readwrite, retain) id aController; then your example works, while if it is defined as #property (readwrite, assign) id aController; then the extra call to release would cause your object to be deallocated.
You could also do
#property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];
with a retaining property, and it would function the same way, but its better to use the other way (for retaining properties) because it's less confusing, that code makes it look like you assign aController and then it gets deleted from memory, when actually it doesn't because setAController retains it.