I'm sorting out some memory issues with my iPhone app and I've just been thinking about some basics. If I setup an ivar and never end up using it in the lifespan of my object, when I call dealloc on it, will that cause a problem? E.g.
#interface testClass {
id myobject;
}
#property (nonatomic, retain) id myobject;
#end
#implementation testClass
#synthesize myobject;
- (id)init {
...
// Do I have to set myobject to nil here?
// So if myobject isn't used the dealloc call to nil
// will be okay? Or can you release the variable without
// having set every object to nil that you may may not use
...
}
...
// Somewhere in the code, myobject may be set to
// an instance of an object via self.myobject = [AnObject grabAnObject]
// but the object may be left alone
...
- (void)dealloc {
[myobject release];
[super dealloc];
}
#end
Instance variables are initialized to 0 before your initializer runs..
Yes, ivars are always initialized to 0/nil/NULL/NO/etc.
However, if it helps you understand what's going on, go for it. The performance impact is negligible. You don't need to do it, but it won't cause any problems if you do.
I find that it is good practice to always set those ivars to nil in the init method. That way, you are absolutely sure that your call to release in the destructor can not cause problems.
If it turns out that Objective-C does automatically set them to nil, and for some reason you find yourself with a speed bottleneck that can be improved upon by removing those assignments (highly unlikely), then you can worry about removing them. In the meantime, set them all to nil and sleep easier :)
update: BJ Homer and Chuck have pointed out that the ivars will automatically be set to zero, so now it comes down to a decision on style.
Related
I am newbie to iPhone programming. I have the following doubt which is stopping me to go ahead. Please consider the following code:
---------.h------
#interface myClass: UIViewController
{
UIImage *temp;
}
#property (nonatomic, retain) UIImage *temp;
---------.m------
#interface myClass
#synthesize temp;
-(void) dealloc
{
[temp release];
[super dealloc];
}
The above is the only program code. Thats it ... nothing else. Do I need to declare [temp release] in dealloc method even though I am not using the property accessor method in my program at all. What if I don't declare [temp release] in dealloc. Will that create memory leak as I am releasing something which I haven't retained as I am not calling property accessor method.
Also when i print retain count for temp why does it show 0 even though it is getting retained in #property.
Thanks in advance
If no value has ever been assigned to (an instance of) myClass.temp, then there won't be a leak. But you should release it in your dealloc.
#property is only a declaration that instance of myClass will have this property. You need to assign it a value before that value gets retained.
myClass *instance = [[myClass alloc] init];
// instance will now retain the value passed in
// and is therefore responsible for releasing it
instance.temp = [UIImage imageNamed:#"whatever"];
// if instance is not retained anywhere else,
// its dealloc will be called
[instance release];
On a sidenote, you should give your classes names that start with an uppercase
letter, i.e. MyClass. Not required, but makes things clearer.
You can also use self.temp = nil; in your dealloc You're sorta not supposed but it kinda works better and looks cleaner. It's a bit of an iffy subject...
What you are doing is correct. Scroll to the "dealloc" section of this Apple Doc: Declared Properties
Soon, however, these properties will be cleaned up automatically when you synthesize them (in the next Cocoa update) -- that being said, a convention I have personally began to follow so that my code works in the future is setting self.temp = nil; in dealloc instead of sending a release message (read the apple doc i posted, it explains this). The accessor method created at runtime releases the object first, so for me and quite a few other devs, this is a better/safer way of cleaning up declared properties in our dealloc.
Your code is correct.
The general rule is that, for all variables you declare in #interface, you must clean them up in -dealloc. Some variables will need to be released, others just need to be nil'd out, depending on how you've declared the #property.
In your example above, temp may never have been given a value explicitly by you, but the ObjC runtime will have initialized the value of temp to nil when an instance of your class gets allocated.
Sending a -release to a nil object is generally not a problem, so the [temp release] is fine. It's a no-op. When temp has a non-nil value in -dealloc, the [temp release] gets to do its job of freeing up the memory.
If you need temp to have a non-nil value on creation, you'll need to implement the -init method and make sure it gets some value. While your class is legitimate & functional without an -init method, you really should get in the habit including one in every custom class you design.
You'll need the default initializer at a minimum: -init. You may also want to design a more detailed initializer that could be used to give your temp ivar an a value, like -initWithImage:
Here's what you should also be including in your class:
#implementation MyClass
...
- (id) init {
self = [super init];
if (self != nil) {
// The minimal default initializer.
// temp will already have a value of nil, so you don't need necessarily
// need to do anything more, unless temp needs a real value on initialization.
}
return self;
}
- (void) dealloc {
...
}
#end
To implement a more detailed initializer, which would be known as the designated initializer, you would to something like this:
#implementation MyClass
...
- (id) initWithImage:(UIImage *)newImage {
self = [super init];
if (self != nil) {
temp = [newImage retain];
}
return self;
}
// Implement the default initializer using your more detailed initializer.
- (id) init {
// In this default initializer, every new instance comes with a temp image!
return [self initWithImage:[UIImage imageNamed:#"foobar"]];
}
- (void) dealloc {
...
}
#end
Here, the designated initializer -initWithImage: is the authoritative initializer. All other initializers, including -init, get implemented using -initWithImage:.
You get to exercise a lot of discretion over whether to implement any initializers beyond the minimal default initializer. Maybe -init is good enough for your purposes. That's fine. Sometimes more detailed initializers make using the class more convenient. Experience (and the Force) will be your guide.
Note that I didn't use the generated property accessor in either initializer method. If you aren't required by circumstances, you should generally avoid using property accessors in -init methods and -dealloc, primarily because of potential pain-in-the-ass issues with side effects of automatic key-value coding notifications.
The initializer and dealloc methods play a special role in a class. As the class designer, it is your responsibility to set and clean up instance variables in these methods. A good rule of thumb is to leave the use of synthesized property accessors for the callers of your class, and the implementation of other methods in the class.
When doing initialization of an instance, or deallocation, you can and should touch the ivars directly. They're yours. You declared them, so you can handle them directly. When implementing other methods in your class, you generally should use the property accessors.
JeremyP's link to the Cocoa Conceptual documentation on objects is a good one. You should definitely read the sections on Objects, and periodically re-read it as you gain more experience writing custom classes of your own. Eventually, it will all start making sense.
When should I be using the self expression in my iphone development applications? say i have 2 fields: UITextField *text1; and NSString *str1; retained and synthesized.
when i am accessing either of these 2 fields, when should i and when should i not use self.text1 and self.str1 ?
self is not a keyword, it is an expression. Additionally, you use it any time you want to refer to a method or property on yourself, or yourself directly. By "yourself" I am of course, referring to the instance of the class you are operating in.
There are certain circumstances where it's generally discouraged to use the self.-expression to access a property. Normally you always use self for any access of a property. It's the most secure and uncomplicated way. Especially if you used retain, then memory management will be done for you.
The two exceptions from this rule:
Any init method.
In dealloc.
In both cases you are dealing with an partially initialized object. There are some side effects that may occur when using setters or getters here -- because they are methods and hence may be overridden.
For example, take a class A with a property foo that has been subclassed by class B. The subclass B adds an property bar and overrode the setter for foo. Now your init-method calls setFoo:, because you used self.foo = ... with some initial value. The subclass, however, also accesses the value of bar in this setter. But in this case, it may happen that bar has never been initialized and points at some arbitrary data. Calling a setter in init my cause crashes, although the probability may not be too high in your own code.
In your example you aren't directly accessing instance variables when you use self, instead you're accessing the properties you've defined.
Consider this example:
#interface Foo : NSObject {
NSString *_bar;
}
#property (nonatomic, retain) NSString *bar;
#end
#implementation Foo
#synthesize bar = _bar;
-(void)baz {
_bar = #"ivar"; //accessing the ivar
self.bar = #"property"; //accessing the ivar via the property
}
#end
In general if you're using properties, there's little reason to utilize the ivar. This has the added benefit of automatically retaining & releasing values for you.
But other cases exist when your properties will have a readonly modifier. In these cases it's necessary to directly access your ivars in order to set their values.
It's also a good idea to use self within a method call sometimes if you have a custom getter. The managedContext object within a Core Data-using application is a good example. If you refer to it by self.managedContext, you can override and set the object to what it needs to be if it's nil. Refer to the code generated by XCode when creating an application that uses Core Data.
Here is an example of the code generated by XCode, actually:
#interface YourAppDelegate : NSObject <UIApplicationDelegate>
{
#private
NSManagedObjectContext *managedObjectContext_;
}
#property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
#implementation ContractionTimerAppDelegate
/**
Returns the managed object context for the application.
If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
*/
- (NSManagedObjectContext *)managedObjectContext {
if (managedObjectContext_ != nil) {
return managedObjectContext_;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext_ = [[NSManagedObjectContext alloc] init];
[managedObjectContext_ setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext_;
}
#end
if you "synthesize" the variable, you should "self." the variable. little rule of thumb
I don't know anything about objective-c, but this looks a lot like this keyword from other languages (like C++, C#, Java, PHP, and others). If so, then my advice is to use it always. That way, if you ever (accidentally) define a local variable with the same name, your code won't break.
However, I must also add, that this is somewhat of a religious debate with a history of flamewars in programmer communities. So take this advice with a grain of salt and use whatever seems to make most sense to you. Just be consistent about it.
I'm new to memory-management, and am reading different things about how to best release properties.
If I have:
in .h:
#property(retain) NSString *myStr;
and in .m:
#synthesize myStr = _iVarStr;
Should my dealloc have:
[_iVarStr release];
or
self.myStr = nil;
or something else?
Thanks!
Both self.myStr = nil and [myStr release] ultimately do the same thing.
Calling [myStr release] is obvious and just releases it.
Meanwhile, the setter method for myStr looks roughly like this:
- (void)setMyStr:(NSString *)newMyStr
{
[newMyStr retain];
[myStr release];
myStr = newMyStr;
}
So when we do self.myStr = nil, we're first retaining a nil object, which does nothing. Then we release the old variable, which is what we want. Finally, we set the pointer to nil.
What's the difference? The latter sets the pointer to nil. This is better because if we (accidentally) send a message to the released object, we crash if the pointer isn't nil (EXC_BAD_ACCESS). Now honestly, since you're in -dealloc, the object is being destroyed anyways, so it wouldn't really matter what you use.
When a property is set to retain then
self.ivar = nil;
will properly manage the memory allocation. For other property types check the at the official documentation page. It also has a bunch of sample code so you can understand what happens "under the hood" for all the options.
Your dealloc should be this:
- (void)dealloc {
[_iVarStr release];
[super dealloc];
}
Although setting the property to nil is possible, I worry about unintended side effects or KVO actions triggered by the change that may not realize the object is currently being deallocated.
I recommend you use self.ivar=nil(the code ivar=nil previously I wrote was wrong) way in dealloc method. Because, if the ivar's property change from retain to assign (or from assign to retain), you don't have to change your code.
I'm doing the following:
- (void) accelerometer: (UIAccelerometer *)accelerometer didAccelerate: (UIAcceleration *)acceleration {
if (self.lastAcceleration) {
double i = self.lastAcceleration.x;
It works fine until I actually tilt the phone. Then I get EXC_BAD_ACCESS on the last line. lastAcceleration is a property with a retain. When I look at "x" in the debugger, it has a large negative value. Why would that throw a EXC_BAD_ACCESS exception only on tilt?
-- EDIT (Since this answer applies to responses below) --
I added this and now it works:
- (void)dealloc {
[lastAcceleration release];
Why would that matter? Also, should it be
[self.lastAcceleration release];
I wasn't previously releasing lastAcceleration anywhere. Here is the header declaration:
#interface MyViewController : UIViewController <UIAccelerometerDelegate> {
UIAcceleration *lastAcceleration;
}
#property(nonatomic, retain) UIAcceleration *lastAcceleration;
#end
My hunch is that the accelerometer API has nothing to do with the crash, the code you have shown smells like bad memory management, given that you're mixing ivar and property access I suspect you might be doing the same in other parts you're not showing.
Anyway a couple best practice things:
any object you have a pointer for in your class you should have retained, and conversely when you release it you should also zap the pointer so you don't risk accessing it after it has been deallocated (the exception to this rule are some patterns like the delegate object, where retaining the object would cause a retain cycle, but that's a whole other topic)
ivar setters and getters that are automatically generated via the #synthesized directive will retain and release the object for you for code that simply looks like it's assigning a pointer, so they're pretty handy, but property access (self.something = ...) and ivar access (something = ...) are not equivalent so you have to be careful
One easy way to make sure you don't mix the two up is to do something like this:
#interface MyObject : NSObject
{
SomethingObject *_something;
}
#property (nonatomic, retain) SomethingObject *something;
#end
#implementation MyObject
#synthesize something = _something;
#end
What we're doing here is making the ivar and property names slightly different, so that you are more aware of which one you're using, and the compiler will bark if you use don't use the bare something = ... syntax.
Now the #synthesize'd accessors are something like this:
- (void)setSomething:(SomethingObject *)newSomething
{
[newSomething retain];
[_something release];
_something = newSomething;
}
- (SomethingObject *)something
{
return _something;
}
With all that out of the way, [lastAcceleration release] is a bad thing to do because it isn't also setting the lastAcceleration pointer to nil, you are not guaranteed that it won't be deallocated and if you accidentally use it you are likely to crash.
[self.lastAcceleration release]; is incorrect because accessors take care of all the retain/release stuff for you.
The correct thing to do here is self.lastAcceleration = nil; that, if you look at the accessor code, will release and set the pointer to nil.
What is likely happening is that you are releasing lastAcceleration somewhere without also setting it to nil, and the if (self.lastAcceleration) { check is hitting a released object.
Main reason to have retained properties is to avoid explicit retain/release calls and memory management bugs associated with them. But in dealloc method either way is fine, since object will cease to exist soon.
[self.lastAcceleration release]; - not necessary.
[lastAcceleration release]; self.lastAcceleration = nil;
Both are fine if used in dealloc.
Outside of dealloc use only
self.lastAcceleration = nil;
EXC_BAD_ACCESS is raised when you access released memory. My guess would be that you somewhere released self.lastAcceleration but didn't set it to null.
Are you sure it is related to tilting?
I'm trying to understand how strategies some folks use to distinguish instance vars vs. properties. A common pattern is the following:
#interface MyClass : NSObject {
NSString *_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#end
#implementation MyClass
#synthesize myVar = _myVar;
Now, I thought the entire premise behind this strategy is so that one can easily distinguish the difference between an ivar and property. So, if I want to use the memory management inherited by a synthesized property, I'd use something such as:
myVar = #"Foo";
The other way would be referencing it via self.[ivar/property here].
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Thanks.
Properties are just setters and getters for ivars and should (almost) always be used instead of direct access.
#interface APerson : NSObject {
// NSString *_name; // necessary for legacy runtime
}
#property(readwrite) NSString *name;
#end
#implementation APerson
#synthesize name; // use name = _name for legacy runtime
#end
#synthesize creates in this case those two methods (not 100% accurate):
- (NSString *)name {
return [[_name copy] autorelease];
}
- (void)setName:(NSString *)value {
[value retain];
[_name release];
_name = value;
}
It's easy now to distinguish between ivars and getters/setters. The accessors have got the self. prefix. You shouldn't access the variables directly anyway.
Your sample code doesn't work as it should be:
_myVar = some_other_object; // _myVar is the ivar, not myVar.
self.myVar = some_other_object; // works too, uses the accessors
A synthesized property named prop is actually represented by two methods prop (returning the current value of the property) and setProp: (setting a new value for prop).
The self.prop syntax is syntactic sugar for calling one of these accessors. In your example, you can do any one of the following to set the property myVar:
self.myVar = #"foo"; // handles retain/release as specified by your property declaration
[self setMyVar: #"foo"]; // handle retain/release
_myVar = #"Foo"; // does not release old object and does not retain the new object
To access properties, use self.propname. To access instance variables use just the instance variable's name.
The problem with using the #synthesize myVar = _myVar strategy, is I figured that writing code such as:
myVar = some_other_object; // doesn't work.
The compiler complains that myVar is undeclared. Why is that the case?
Because the variable myVar is undeclared.
That statement uses the syntax to access a variable, be it an instance variable or some other kind. As rincewind told you, to access a property, you must use either the property-access syntax (self.myVar = someOtherObject) or an explicit message to the accessor method ([self setMyVar:someOtherObject]).
Otherwise, you're attempting to access a variable, and since you don't have a variable named myVar, you're attempting to access a variable that doesn't exist.
In general, I name my properties the same as my instance variables; this is the default assumption that the #property syntax makes. If you find you're fighting the defaults, you're doing it wrong (or your framework sux, which is not the case for Cocoa/Cocoa-touch in my opinion).
The compiler error you're getting is because property use always has to have an object reference, even inside your own class implementation:
self.stuff = #"foo"; // property setter
[stuff release]; // instance variable
stuff = #"bar"; // instance variable
return self.stuff; // property getter
I know that many Cocoa programmers disagree, but I think it's bad practice to use properties inside your class implementation. I'd rather see something like this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
[stuff release];
stuff = [theStuff copy];
// do something else
}
than this:
-(void) someActionWithStuff: (NSString*) theStuff {
// do something
self.stuff = theStuff;
// do something else
}
I prefer to do memory management as explicitly as possible. But even if you disagree, using the self.stuff form will clue in any experienced Objective-C programmer that you're calling a property rather than accessing an instance variable. It's a subtle point that's easy for beginners to gloss over, but after you've worked with Objective-C 2.0 for a while, it's pretty clear.
Don,
According to the "rules", you should call Release for every Copy, Alloc, and Retain. So why are you calling Release on stuff? Is this assuming it was created using Alloc, Copy, or Retain?
This brings up another question: Is it harmful to call Release on a reference to an object if it's already been released?
Since Apple reserves the _ prefix for itself, and since I prefer to make it more obvious when I am using the setter and when I am using the ivar, I have adopted the practive of using a prefix of i_ on my ivars, so for example:
#interface MyClass : NSObject {
NSString *i_myVar;
}
#property (nonatomic, retain) NSString *myVar;
#synthesize myVar = i_myVar;
i_myVar = [input retain];
self.myVar = anotherInput;
[i_myVar release]
Since it is quite important to know when you are using the setter and when you are using the ivar, I find the explicitly different name is safer.
In your question, it should be:
self.myVar = #"Foo"; // with setter, equivalent to [self setMyVar:#"Foo"]
and
_myVar = some_other_object; // direct ivar access - no memory management!
Remember that you should not use setters/getters in init/dealloc, so you need to do your direct ivar access (and careful memory management) iin those methods.
what's wrong with simply using
#interface MyClass : NSObject
#property NSString *prop;
#end
nonatomic and retain are not required, retain is the default, and atomic/nonatomic isn\t important unless XCode tells you with a warning.
it is NOT necessary to declare the iVar, one will be created for you named _prop, if you really want to use one (i don't see why to be honest)
#synthesize is NOT required.
when (and you should) using ARC you don't have to bother with retain and release either.
keep it simple !
furthermore, if you have a method like this one
- (void)aMethod:(NSString*)string
{
self.prop = string;
// shows very clearly that we are setting the property of our object
_aName = string;
// what is _aName ? the _ is a convention, not a real visual help
}
i would always use properties, more flexible, easier to read.