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.
Related
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.
The title says everything!
In Objective-C, what's the difference between self.propertyName vs. propertyName?
self.propertyName is sending the object a message, asking it for the value of propertyName, which means it may go through a getter/setter, etc. propertyName is directly accessing the ivar, bypassing any getter/setter. Here's an article going into it in rather more detail.
self.propertyName increse the retain count by one if you have specified the propertyName as retain in property declaration
propertyName will not increase the retain count an could lead to the crash of application.
e. g. ,
#property (nonatomic,retain) NSString* propertyName;
lets say you have nameProperty NSString object.
Below increase the retain count by 1 and you could use self.propertyName and call release.
self.propertyName = nameProperty;
[nameProperty release];
Below does'nt increase the retain count so if you use propertyName in your application it will result in crashing of your application.
propertyName = nameProperty;
[nameProperty release];
Any further use of propertyName will result in crash.
self. runs through your likely synthesized accessor methods if you are using properties
ie self.propertyName = newName is the same as [self setPropertyName:newName]
This becomes important for memory management as propertyName = newName would cause you to loose reference to the previous contents of propertyName
If you call self, you can be sure you're calling the class/object that owns the property.
You may find this useful too:
Assigning to self in Objective-C
dot notation is turned into a method call by the compiler. This means that there is extra work at run time for executing this method call, like copying something from and to the stack memory and executing a jump in machine code.
the instance variable by itself is faster because it is essentially just a memory address or scalar value (like int).
One would prefer the self.something notation when you want or need an extra layer to do something. Like retain an object that is passed in or lazily instantiate an object on the first time you need it.
Setting the value of the property does just that - it sets the value of the property directly without going through any accessors or synthesized accessors.
By calling the accessor through self you are going through the accessors. For properties that have been declared with retain or copy it will retain or copy the value that is passed in. For non objecte properties, the usual declaration is assign which means that there is no memory management applied to those iVars.
You see both types of calls - but it is preferred to use the direct method in initialisers and the dealloc method, because calls to self are discouraged in these methods.
If you have declared and synthesized the property, the call to self also generates the KVO notifications for changes in that variable. This saves you having to write the willChangeValueForKey: and didChangeValueForKey: methods.
I have a question about a retain and a NSString, if I have a method who a return a NSString, and I put the return NSString in a nsstring variable, I must do a retain or not?
NSString *myString = #"";
myString = [self methodWhoReturnString]; // I must do this?
myString = [[self methodWhoReturnString]retain]; // Or I must do this?
The Apple Developer Documentation on Memory Management explains the scenarios where you retain/release objects.
Simply put, if you want the string to stick around, you need to retain it until you're finished with it. If that is just the scope of the current function, you can get away without retaining it as if the string is already autorelease'd (likely) it won't get released until your function finishes and the current AutoReleasePool is purged.
Bear in mind that an NSString * could actually be pointing to an NSMutableString *. If it matters to you if the string is changed by some other function without you realizing, be sure to copy it: NSString * myCopyOfString = [mystring copy];
If the string is set to autorelease, which it most likely is, then yes you will need to retain it somehow. I would suggest doing this though:
myString = [[self methodWhoReturnString] copy];
this ensures you have retained the data in the string not just a reference to a string that might still be controlled elsewhere. Be sure you release your copy later!
Usually, methodWhoReturnString would return an autoreleased string, which means you should retain it if you want to keep it around.
So, if methodWhoReturnString is your method, I believe that to keep with convention you should return [stringToReturn autorelease]; from that method, and then retain it if you want to keep it.
You use retain if you're going to be using myString at a later point in time (i.e. after the current method has returned) to prevent it being autoreleased.
You don't need to use retain if it's just a temporary variable used within the current method, since in that case you do want it to be autoreleased.
One special case is properties. If you call self.blah = foo, you don't need to retain foo, since the setBlah: method should do it for you.
(there's a whole load of other complexities and edge cases, but this is a good rule of thumb to get you started on understanding what to do)
Given the code you provided, you shouldn't call -retain. In your example, the return value of a method that returns an instance of NSString is assigned to myString, an automatic local variable. If the assignment had been made to an instance variable or a static variable, you would want to call either retain or copy to guarantee that the reference remains valid beyond the end of the local scope.
In this case though, the reference to the NSString instance is stored in a variable that will be destroyed automatically at the end of the local scope, so your code needn't concern itself with the object's lifetime.
Any method that has alloc, new or copy in it automatically retains and infers that you have ownership of the object. All others shouldn't. It would be helpful if you had more context though. If we are in a contained method where this string is used briefly, then you probably don't need to retain. If it is going to be used for a while, you might want to use the #synthesize syntax to make it a property of the class you are in. When you use #property and #synthesize and call something like self.myProperty = something it will automatically retain.
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.
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.