I am newbie to iPhone programming. I am not using Interface Builder in my programming. I have some doubt about memory management, #property topics in iPhone.
Consider the following code
#interface LoadFlag : UIViewController {
UIImage *flag;
UIImageView *preview;
}
#property (nonatomic, retain) UIImageView *preview;
#property (nonatomic, retain) UIImage *flag;
...
#implementation LoadFlag
#synthesize preview;
#synthesize flag;
- (void)viewDidLoad
{
flag = [UIImage imageNamed:#"myImage.png"]];
NSLog(#"Preview: %d\n",[preview retainCount]); //Count: 0 but shouldn't it be 1 as I am retaining it in #property in interface file
preview=[[UIImageView alloc]init];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 1
preview.frame=CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
preview.image = flag;
[self.view addSubview:preview];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 2
[preview release];
NSLog(#"Count: %d\n",[preview retainCount]); //Count: 1
}
...
When & Why(what is the need) do I have to set #property with retain (in above case for UIImage & UIImageView) ? I saw this statement in many sample programs but didn't understood the need of it.
When I declare #property (nonatomic, retain) UIImageView *preview; statement the retain Count is 0. Why doesn't it increase by 1 inspite of retaining it in #property.
Also when I declare [self.view addSubview:preview]; then retain Count increments by 1 again. In this case does the "Autorelease pool" releases for us later or we have to take care of releasing it. I am not sure but I think that the Autorelease should handle it as we didn't explicitly retained it so why should we worry of releasing it.
Now, after the [preview release]; statement my count is 1. Now I don't need UIImageView anymore in my program so when and where should I release it so that the count becomes 0 and the memory gets deallocated. Again, I am not sure but I think that the Autorelease should handle it as we didn't explicitly retained it so why should we worry of releasing it. What will happen if I release it in -(void) dealloc method
In the statement -> flag = [UIImage imageNamed:#"myImage.png"]]; I haven't allocated any memory to flag but how can I still use it in my program. In this case if I do not allocate memory then who allocates & deallocates memory to it or is the "flag" just a reference pointing to -> [UIImage imageNamed:#"myImage.png"]];. If it is a reference only then do i need to release it.
You say...
I am newbie to iPhone programming. I
am not using Interface Builder in my
programming.
Wait. What? Why not? Not using IB as someone new to the environment is generally an indication that you are doing your app the hard way. Not using IB for app development is reserved for rare, generally fairly advanced, situations.
Question 1
This means that the synthesized property accessor messages will include an automatic retain when the message is called (but ONLY when the message is called, see next).
Question 2
This is because you are not using the property accessor message, you are just assigning to the member variable. If you use:
self.preview = [[[UIImageView alloc] init] autorelease];
The resulting retain count will be one (+1 for the init, -1 for the autorelease, +1 for the retain on the message).
N.B.
You will get the same retain count (one) if you do this:
preview = [[UIImageView alloc] init];
(+1 for the init, not using the property accessor message so no extra retain). Up to you which way you go with.
Question 3
The addSubview will increment the retain count again because the preview will be stored in a collection which will retain it's objects.
So yes, Basically if you are handing an object off to another object to manage (as is the case with addSubview) you can set it to autorelease and it will be released by the other object. However, since you are storing the UIImageVIew in a retained property, you will need to release it yourself (see next).
Question 4
Because you are keeping the preview object as retained property, you will need to release it in your dealloc message. So in my Question 2 example, you allocate the object, autorelease it, but assign it to retained property, so the retain count after all that will be one, you are adding it to a collection which will also retain it. When the view is cleaned up the collection will decrement the retain count, but you will need to call release as well, because you stored it in a retained property. So in your dealloc:
[preview release];
Question 5
imageNamed is a helper message that does the allocation, initialization and autorelease. So basically it is equivalent to saying.
NSData * dataForImage = get data from the myImage.png here ...
self.flag = [[[UIImage alloc] initWithData:dataForImage] autorelease];
You are storing it in a retained property (because I use self.flag in the above example), so you will need to release it in the dealloc message.
When you write
flag = [UIImage imageNamed:#"myImage.png"]];
you are assigning to the instance variable directly, bypassing the property accessor. Instead you need to use the dot-notation:
self.flag = [UIImage imageNamed:#"myImage.png"]];
That explains your retain count problem.
I found it useful to declare the instance variables with a different name, like _flag for a property flag. Associate the two by writing
#property .... flag = _flag;
That way you will not accidentally use the variable directly. You can, of course, still do so if the need arises.
You use retain to claim ownership of an object. This essentially means that when something is assigned to the property, you ensure that it's there for as long as the owning object needs it.
#property ... is a statement of your the interface of your class. It doesn't mean there is a value for the property in question, only that "Instances of LoadClass have a flag property which is retained by it". Not until you actually assign values to the properties of an instance will things be retained.
This is because UIView claims ownership of its subviews.
Your object might not need it, but UIView still needs it.
It's autoreleased by UIImage.
You should read the full guide on Memory Management by Apple. I try to think of memory management as owning objects or not... it helps.
Question 2: The #property statement in your #interface is really just a directive to the compiler to automatically generate accessor methods for an instance variable that have the characteristics you specify. #property doesn't cause any actions to happen when you run your code. The compiler will look at the #property line and generate invisible accessor code for you.
#property (nonatomic, retain) UIImageView *preview;
would cause the compiler to generate accessor methods that look something like this:
- (void) setPreview:(UIImageView *)newValue {
[self willChangeValueForKey:#"preview"];
if (preview != newValue) {
[preview release];
preview = [newValue retain];
}
[self didChangeValueForKey:#"preview"];
}
- (UIImageView *) preview {
return preview;
}
#property is a timesaver for you; it directs the compiler to generate accessor code for your variables that are efficient but invisible. If you didn't use #property, you'd have to write accessor methods similar to the above in your custom class.
Related
I am working on an iphone application, and although I thought I had a good understanding of memory management, I'm seeing some issues after using the Xcode Analyze function. I have looked at many of the existing questions I could find on here, but I couldn't find one that was similar to my situation.
CustomerDetailController.h
#interface CustomerDetailController : UITableViewController {
PTCustomer *customer;
}
#property (nonatomic, retain) PTCustomer *customer;
- (id)initWithCustomer:(PTCustomer *)aCustomer;
CustomerDetailController.m
#synthesize customer;
- (id)initWithCustomer:(PTCustomer *)aCustomer {
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
if (aCustomer != nil)
self.customer = aCustomer;
else
self.customer = [[PTCustomer alloc] init]; // This line shows Potential leak of an object allocated on line ##
}
return self;
}
If I click on the item marked by the Analyzer, it then says:
Method returns an Objective-C object with a +1 retain count
Object leaked: allocated object is not referenced later in this execution path and has a retain count of +1
My reasoning behind this is that if a PTCustomer object was not passed in, I want to initialize a new one so that I have it available elsewhere within this class.
What is the correct way to do this?
Thanks.
self.customer is being over-retained.
+1 for alloc of customer
+1 when the property setter retains customer.
Do not retain customer, the property setter will retain it.
Just:
self.customer = [[[PTCustomer alloc] init] autorelease];
But given that this is an init method there is a strong argument that the ivar should be assigned directly:
customer = [[PTCustomer alloc] init];
The other option is to assign the retained object directly to customer rather than to self.customer. This bypasses the auto-retain logic in the setCustomer method. However, if you do that you must assure that any prior object referenced by customer is released (eg, by assigning nil to self.customer).
(Because bypassing the setter in this way is a somewhat irregular technique some folks frown on it.)
Are you releasing your customer ivar in the dealloc? If not, there's your leak.
.h
# interface MyClass : NSObject {
UILabel *mTextLabel;
}
#property (nonatomic, retain) UILabel *mTextLabel;
and Declare #synthesize mTextLabel in the MyClass.m;
and release the object like this.
[self setMTextLabel:nil];
[mTextLabel release];
NSLog (#"%d",[mTextLabel retainCount]);
This result is 0. and I have not found any error or interrupt.
But. When I release mTextLabel like this. I have just got EXC_BAD_ACCESS
[mTextLabel release];
[self setMTextLabel:nil];
I don't understand why it happen. Plz help me.
When you have a synthesized property with the retain attribute, the synthesized setter calls release on the old ivar before it sets the new value.
Here is an expanded view of what is happening in the first example:
[mTextLabel release];
mTextLabel = nil;
[mTextLabel release];
Since calling a method on a nil pointer does nothing, there is no problem.
In the second example, here is what is happening:
[mTextLabel release];
[mTextLabel release];
mTextLabel = nil;
See the problem?
Edit: it is also worth noting that inspecting the retain count of an object is rarely useful, as any number of Cocoa classes may retain it for their own purposes. You just need to be sure that every time you call retain, alloc, copy or new on an object, there is a matching release or autorelease somewhere in your code.
The problem is you are calling release then you are setting the property to nil which also sends a release to mTextLabel before setting it to nil. This is what happens when the property is defined as copy or retain. All you need is the following code.
[mTextLabel release];
mTextLabel = nil;
Edit:
I would like to add that in your code outside of init and dealloc it is completely fine to call self.mTextLabel = nil to properly release if necessary and nil the value of the property. It is however recommended to NOT use the property in the init/dealloc calls. In those cases you will want to create / release the objects directly to avoid the side effects of the accessor.
The value is already released when you do [self setMTextLabel:nil]. You don't need to release the value explicitly (unless you created the value using an init or copy method, in which case you should release it as soon as you've assigned to self.mTextLabel).
Note that retainCount has a return type of NSUInteger, so cannot ever be negative. So checking to make sure the retain count is zero and not -1 doesn't work.
Can anyone explain the difference between setting someObject = someOtherObject; and self.someObject = someOtherObject; if someObject is a class property created with #property (nonatomic, retain) SomeType someObject;
To clarify I have something like:
#interface SomeClass : NSObject {
SomeType* someObject;
}
#property (nonatomic, retain) SomeType* someObject;
#end
I have noticed I get EXC_BAD ACCESS sometimes when I use the property without self and it seems quite random. When I use self my program acts as it should be. I don’t get any compiler errors or warnings when I skip self so I guess it is somehow valid syntax?
self.someObject = someOtherObject makes use of the property. Properties generate setters and getters for you. In your case, you gave the retain attribute to the property, which means that an object set via this property will automatically receive a retain message which increases its retain count by 1. Additionally, the old value of the member variable is sent a release message which decreases its retain count.
Obects are being deallocated, when their retain count reaches 0. You get an EXC_BAD_ACCESS ecxeption if you try to access a deallocated object (e.g. if you try to release it too often).
In your case:
SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
self.someObject = soo; //soo's retain count is now 2
[soo release]; //soo's retain count is 1 again, as self still uses it.
[self doSomethingWithSoo];
However, if you do not use the setter, you must not release soo.
SomeOtherObject *soo = [[SomeOtherObject alloc] init]; //retain count: 1
someObject = soo; //soo's retain count is still 1
[soo release]; //soo's retain count is 0, it will be deallocated
[self doSomethingWithSoo]; //will fail with an EXC_BAD_ACCESS exception, as soo does not exist anymore.
Properties are just a convenient way to access the data. So when you are declaring the property #property (nonatomic, retain) SomeType* someObject; this means that during access there would be synthesized 2 methods:
getter:
-(SomeType*) someObject {
return someObject;
}
setter
-(void) setSomeObject:(SomeType*) obj {
[someObject release];
someObject = [obj retain];
}
So the main difference between properties and ivars is that properties dynamically creating the setter/getter methods (and you can override them). But when you're writing someObject = new_val, you're just copying the reference to the memory location. No additional work is done there except one assembly instruction.
There is one more thing to mention: atomic and nonatomic.
With atomic, the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.
In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than atomic.
Edit: so if you have some variable, that is accessed from different threads or/and some additional work has to be done (e.g. retain, raise some flags ...), then your choice is property. But sometimes you have a variable, that is accessed very often and access via property can lead to a big overhead, because processor has to perform much more operations to synthesize and call method.
It's all about memory management.
Your class property someObject have generated accessors with annotation #property / #synthsize in your .h / .m files.
When you are accessing you property with someObject, you directly access the property. When you are accessing self.someObject you are calling your accessor [self someObject] whitch take care of memory management for you.
So when you need to assign a class property it's cleaner to do self.someObject = someOtherObject; because you use the setter and does not have to take care about releasing and retaining. When your setter is generated with #property (nonatomic, retain) so it will take care about retaining for you.
The difference between the two is:
1) when you do not use "self." you are assigning the result directly to the member variable.
2) when you are using "self." you are calling the setter method on that property. It is the same as [self setMyObject:...];
so in case of self.myobject, it keeps its retain, and in other case, (without self), if you are not using alloc, then it will be treated as autoreleased object.
In most cases you will find you want to use "self.", except during the initialization of the object.
By the way, you can also use self.someObject = [someOtherObject retain] to increase retain counter
I'm constructing a small iphone app and using a singleton to store and update a string that gets updated when the user taps letters or numbers on the screen to form a code.
i.e. they tap 3 then S then 4 and I need to track and combine that input to give me "3S4" say. When the singleton is initialised it creates an empty NSString and I then use the stringByAppendString method to add on the next letter/number tapped. When I first tried this I did not have the [enteredCode retain] line in there and the app would crash with EXC_BAD_ACCESS, always after 2 inputs. I set the NSZombie property which told me that the enteredCode had been de-allocated but I don't know where or how that happened. All I know is that at the end of the addInput method it will report the retainCount to be 2 say and then straight after I can see (by calling the singleton from elsewhere) it will drop down to 1 (when the retain line is in there).
My question is: though what I've done by adding [enteredCode retain] works for me am I breaking some rules here or going about this in the wrong/bad way? I just can't see why the string is being released.
I'm new to Objective-C btw
in MySingleton.h
#interface MySingleton : NSObject {
NSString *enteredCode;
}
in MySingleton.m
-(void) addInput:(NSString *) input
{
NSLog(#"enteredCode retain count is : %d \n ",[enteredCode retainCount]);
enteredCode = [enteredCode stringByAppendingString:input];
NSLog(#"enteredCode retain count is : %d \n ",[enteredCode retainCount]);
[enteredCode retain]; // without this the app crashes
NSLog(#"enteredCode retain count is : %d \n ",[enteredCode retainCount]);
}
-(id) init
{
self = [super init];
if (self)
{
enteredCode = #"";
}
return self;
}
First, never use the -retainCount method. The absolute count of retains on an object is an implementation detail of the frameworks and will often return confusing results.
Retain counts are something you should maintain entirely as a balanced set of deltas. If you cause a retain count to be added to something, you must release or autorelease that object somewhere. End of story.
This document explains it all.
With that knowledge in hand, the source of your crash is a fairly common memory management mistake.
enteredCode = [enteredCode stringByAppendingString:input];
Every time that line of code is executed, you are replacing enteredCode with an autoreleased instance of NSString. The autorelease pool is drained and your program crashes the next time enteredCode is used.
Your solution of retaining enteredCode is only half the solution. You need to ensure that the original value of enteredCode is released, too. See the memory management docs.
If this were my app, I would turn enteredCode into an #property that copies the string and always set and access enteredCode through that property, never retaining or releasing it manually in my code (outside of -dealloc, of course).
NSString's stringByAppendingString: returns a new NSString made by appending one string to the other, and the new NSString is set to autorelease, which empties the autorelease pool and your next run crashes the app. You're redefining an existing string with stringByAppendingString:, and that's causing the retain problems. (Alternatively, use NSMutableString and you can avoid this.)
By the way, you can do if (self = [super init]) in your init override. The declaration returns true if it occurs or can occur.
Here's how your code should look:
#interface MySingleton : NSObject {
NSString *enteredCode;
}
#property (nonatomic, retain) NSString *enteredCode;
#end
#synthesize enteredCode;
-(void) addInput:(NSString *) input
{
self.enteredCode = [self.enteredCode stringByAppendingString:input];
}
- (void)dealloc {
[enteredCode release];
}
#end
The statement is:
//Pass the copy onto the child controller
self.childController.theFoodFacilityCopy = [self.theFoodFacility copy];
My property is set to:
#property (nonatomic, retain) FoodFacility *theFoodFacilityCopy;
The reason I think I have a leak is because copy retains the value and then my dot syntax property also retains the value. Doubly retained.
What is the correct way of writing the above statement?
yes, you do have a leak there.
SomeClass *someObj = [self.theFoodFacility copy];
self.childController.theFoodFacilityCopy = someObj;
[someObj release];
This mirrors the recommended approach for initializing an object too:
SomeClass *someObj = [[SomeClass alloc] init];
self.someProperty = someObj;
[someObj release];
In both cases the first line returns an objects with a retain count of 1, and you treat it identically after that.
As mentioned by others, that is indeed a leak. If you expect to be using copies in this way, it’s likely your property should be declared copy instead and the synthesized accessor will do the work for you.
You are right. The cleanest way is something like
id temp = [self.theFoodFacitlity copy];
self.childController.theFoodFacilityCopy = temp;
[temp release]
You want to read the apple site on memory management a lot until these rules become second nature.
What is the advantage of doing this vs just setting the property to copy?
#property (nonatomic, copy) FoodFacility *theFoodFacilityCopy;