Do I need to release my singleton object? - objective-c

I have a singleton object in my app:
+ (id)shared {
#synchronized(self) {
if (sharedDownloadFirstData == nil)
sharedDownloadFirstData = [[self alloc] init];
}
return sharedDownloadFirstData;
}
- (id) init {
if (self = [super init]) {
}
return self;
}
And I want to know if I need to realese it (I am not using ARC). To do that I am using:
[[DownloadFirstData shared] release];
Did I need to release this object? I have an array and other stuff in the object that I need to release.

In Objective-C, you should only ever call release on an object you own. This typically means an object you've created with alloc, init, copy or mutableCopy or otherwise called retain on. Here, the consumer of [DownloadFirstData shared] didn't call any of those functions and is not responsible for releasing it. You will see this any time you call [UIColor blackColor], for instance.
You may want to call retain on such an object, if you are crossing autorelease boundaries or are just not sure of the lifetime:
DownloadFirstData *local = [[DownloadFirstData shared] retain];
...
[local release];
In this case, you've taken ownership and are responsible for releasing.
But what about the definition of shared? When you define a method not using init..., you are typically responsible for leaving with a release count of 0, with something like [[self alloc] init] autorelease]. This is not the case for the singleton because your goal is for it to always exist and therefore always have a non-zero retain count. You make this happen simply by not releasing it after you create it.

there is no sense in having a singleton if you will release it.
Usually a singleton is created because you want the same object till the app ends.
At the end of your app life cycle all memory related to the app is freed.
Use a standard approach, if you need alloc release often.
if your singleton takes a lot of memory, you should consider to write it better.
anyway, [[DownloadFirstData shared] release]; will work.

Related

Managing Memory in Objective c

I am doing my project in xcode 4.2 (Older Version). For my application, I just set the variables, arrays in dto class for using in entire app lifecycle. so I set with a property like this.
AppDTO(sub class of NSObject)
AppDTO.h
#property(nonatomic,retain)anotherAppDTO *aAppDTO;
#property(nonatomic,retain)NSMutableArray *array1;
#property(nonatomic,retain)NSMutableArray *array2;
#property(nonatomic,retain)NSString *string1,*string2,*string3;
AppDTO.m
- (id)init
{
self = [super init];
if (self) {
self.aAppDTO = [[anotherAppDTO alloc]init];
self.array1 = [[NSMutableArray alloc]init];
self.array2 = [[NSMutableArray alloc]init];
self.string1 = #"Hello";
self.string2= #"Hai";
}
}
-(void)dealloc
{
if(array1 != nil)
{
[array1 release];
array1 = nil;
}
if(array2 != nil)
{
[array2 release];
array2 = nil;
}
[aAppDTO release];
aAppDTO = nil;
[super dealloc];
}
when I analyze my app in Xcode 4.3.2, I get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when I change self.array1 to array1, warning goes away.
What is the reason for using self. do I need to use self if I set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
Also in dealloc method, I heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
Do I need to release my string in dealloc method.
Also I am releasing aAppDTO in dealloc method. if I allocate some objects in anotherAppDTO class, will it release automatically when I call [aAppDTO release] method.
Can anyone clarify me.
Many Thanks,
Anish
You get the warning because when you write :
self.array1 = [[NSMutableArray alloc]init];
is the same as :
[self setArray1: [[NSMutableArray alloc]init]];
As you can notice you are not allocating the underlying array1 private variable, but you are calling the setter of the property that since it is declared as retain it retains the object once assigned, this means that when you eventually will assign another object the second time with the setter the first object will remain with a retain count of one until the application will be closed (since you don't have any reference to that object anymore ...) .
Take a look at this great article to understand better Manual Reference Counting in Objective-C .
when i analyze my app in Xcode 4.3.2, i get memory warning in self.array1 and self.array2 (Potential leak on object allocated on line….), but when i change self.array1 to array1, warning goes away.
the analyzer's right. the parameter is retained when set. as well, you should favor direct access in initialization and dealloc. so, you should just write array1 = [[NSMutableArray alloc] init];, and be done.
What is the reason for using self. do i need to use self if i set #property(nonatomic,retain) to variables(like array1,array2,string1,string2).
those go through the accessor methods. if not in initialization or dealloc, you should favor going through the accessor methods because that is the common correct execution path for a fully constructed object.
Also in dealloc method, i heard we don't want to use [self.array1 release], instead we can use [array1 release]. Is it Correct?
correct.
Do i need to release my string in dealloc method.
yes.
Also I am releasing aAppDTO in dealloc method. if i allocate some objects in anotherAppDTO class, will it release automatically when i call [aAppDTO release] method.
when its reference count reaches 0, its dealloc will be called.
I think the others have answered your question.
I do want to draw your attention to Apple's excellent Advance Memory Management Programming Guide: Practical Memory Management, in which they walk through these sorts of scenarios. It's hard to take it all in on the first reading, but it really does cover this stuff. In answer to your question about the use of instance variables versus the accessor methods, I draw your attention to the section labeled to "Don't Use Accessor Methods in Initializer Methods and dealloc".

Potential leak of an object warning -- clarification needed

After I Analyzed my code, Xcode indicated a potential leak as shown below.
Is this something I should be concerned about?
In this code, the class that sets doublyLinkedList is the sole owner and continues to manage this object throughout program execution.
The reason you're getting the warning is because the new call returns a retained object, and then your setter is probably doing another retain on it (depends on whether it's synthesized or manually generated).
Also, I would recommend you use the standard alloc/init instead of new, so that the two-phase creation is obvious.
This is better:
if (self) {
DoublyLinkedList *dll = [[[DoublyLinkedList alloc] init] autorelease];
self.doublyLinkedList = dll;
}
or just
if (self) {
self.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease];
}
You may wish to do this instead:
if (self) {
DoublyLinkedList *dll = [DoublyLinkedList new];
self.doublyLinkedList = dll;
[dll release];
}
In the header, declare doublyLinkedList a #property that is retained.
You have a "potential leak" because the Analyzer sees that you have allocated memory for a DoublyLinkedList instance (using new), put it into a local variable called dll, and not released that memory in the same scope.
Assuming that the doublyLinkedList member that you're setting happens to also be a property declared as retaining, you also have an actual leak, because you have over-retained the DoublyLinkedList that you create here.
The ownership rules say that you have one claim on this instance because you called new to create it. When you pass the instance to setDoublyLinkedList:, it is retained, and you then have two claims. When the init method ends, you only have one reference to the instance, through the ivar/property -- you've lost the local variable -- which means that you have more ownership claims than you have references. This is a good indication that you will have a leak.
To fix the leak, you need to relinquish one of your claims before the end of the init method. You can do this in one of two ways, using release as soon as the property is set:
DoublyLinkedList * dll = [DoublyLinkedList new];
[self setDoublyLinkedList:dll];
[dll release];
or autorelease:
[self setDoublyLinkedList:[[DoublyLinkedList new] autorelease]];
// Or equivalent procedures involving a temp variable
However, it should be noted that using setters in init may be problematic (see also Mike Ash's writeup on the topic), because accessors can -- potentially -- have side effects that depend on your object already being fully set up. There seem to be two camps on this issue, and it's probably best to read about it and come to your own conclusions, but you may find that it simplifies your initializer methods to assign to ivars rather than using properties:
if( self ){
doublyLinkedList = [DoublyLinkedList new];
}
This is completely correct in terms of memory management.
Finally, if DoublyLinkedList is a class whose code you have, you can also consider writing a convenience constructor, which will return a new, autoreleased instance for you. The convention in Cocoa is to simply name the method after the class, with standard method name casing, like so:
+ (id) doublyLinkedList {
return [[[self alloc] init] autorelease];
}
Note that this is a class method:
if( self ){
[self setDoublyLinkedList:[DoublyLinkedList doublyLinkedList]];
}
and see my answer to "Self-allocating objects" for an explanation of these constructors.
If you have a property called "doublyLinkedList" (assumption based on code given), and it is "retained," you can do the following:
if (self) {
DoublyLinkedList *dll = [[DoublyLinkedList alloc] init]
self.doublyLinkedList = dll;
[dll release];
}

Obj-c autorelease a variable up a chain of methods

I'm new to Obj-C and I have a question concerning the autorelease. Is it ok to return an autoreleased variable for several methods? For example:
- (void) methodC {
Object anObj = [self methodB];
//Do something with anObj
}
- (Object *) methodB {
return [self methodA];
}
- (Object *) methodA {
Object anObj = [[anObj alloc] init];
release [anObj autorelease];
}
Will the variable remain valid even if it is returned up a method chain and used at the top? Or does it have to be retained somewhere along the way?
thank you
Yes, it will be valid in this case. You only have to worry about the variable being deallocated if somebody drains the autorelease pool. As long as you've written every function that returns along the way and you don't explicitly drain the autorelease pool, you don't have to worry about objects being deallocated from under you.
In the vast majority of cases, the code in the NSRunLoop takes care of draining the autorelease pool. When you return control from your application code to the API code (such as by returning from a touchesBegan handler etc.), you don't know if the autorelease pool will be drained, so you have to assume in the worst case that it will. In that case, you have to retain any objects you want to keep references to.
For example:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Object *anObj = [self methodC]; // Your methodC as before -- anObj is valid
[pool drain]; // anObj will be deallocated here
The variable should remain valid. You only need to retain an object if it is actually "owned" by some other object and could be indirectly/unintentionally released along with it. For example, if you extracted an object from an array and then released the array, your object reference could become invalid unless you explicitly retain it.
For more details, see Object Ownership and Dismissal, particularly the sections on Autorelease and Validity of Shared Objects. The latter uses the following code to illustrate how you could "accidentally" make an object reference invalid.
heisenObject = [array objectAtIndex:n];
[array removeObjectAtIndex:n];
// heisenObject could now be invalid.
The following code shows how to mitigate this problem using retain.
heisenObject = [[array objectAtIndex:n] retain];
[array removeObjectAtIndex:n];
// use heisenObject.
[heisenObject release];

Why always leak when using CLLocationManager?

myclass.m
- (id) init {
self = [super init];
if (self != nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self; // send loc updates to myself
}
return self;
}
- (void)dealloc {
[locationManager release];
[super dealloc];
}
I use instrument to check leak. The leak always point to
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
Why?
I use instrument to check leak. The
leak always point to
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
Why?
Because that is the line of code where the allocation that is leaked occurred. Since you have balanced both implied retains in that code correctly (once here, once in -dealloc -- mmccomb's suggestion of direct assignment without autorelease is good, but won't fix the problem), the leak is elsewhere.
Specifically, the leak will be a retain that isn't balanced by a release. So, somewhere your are retaining the object and not releasing it.
Instruments can be used to show all retain/release events on any given object. Use that and look through the list of events related to your leaked object. There will be one more retain than release. Pair off the retains and releases. Whichever retain is left without a balanced release is the cause.
I wrote an article about using Heapshot analysis in Instruments to detect memory abuse. It includes discussion and screenshots showing the retain/release event inspector and will be applicable.
Try to avoid using the self. setter notation in init methods. When an object is being initialised there is no guarantee that it is in a consistent state. Change your implementation to directly set the ivar as follows...
locationManager = [[CLLocationManager alloc] init];
You no longer need the autorelease call which was previously accounting for the extra retain count brought about by invoking the setter. You do however need to release the object in your dealloc method (as you are already doing).
You can explicitly check the retain count in dealloc like so:
NSLog(#"locationManager retain count: %d", [locationManager retainCount]);
If it is more than 1, check where else you may be retaining it - like if you assign it to another retaining property (e.g. declared with retain keyword). You can add that NSLog call in other locations before and after you do something with locationManager and see where the retain count increases. Sometimes it may not be immediately obvious.
Another possibility: does the dealloc method even get called? Perhaps the whole "myclass" object is not properly released? (Although I suppose in that case you'd see a leak of type "myclass", too).

Some beginner Objective-C/iPhone questions

I'm just starting out (reading up a lot for the past couple of days). Here's some questions that I have stacked up, hopefully someone can answer them.
1. the (self != nil) check in initializer code. Why do it? To prevent accidental access to some "run-only-once" code that's wrapped up in there? Where from could this accidental access come from? Doing such checks suggest that I don't have control over what's going on.
- (id)init {
self = [super init]
if (self != nil) {
// Code..
}
return self;
}
2. How is it that you don't have to free up anything that static methods return? (or this is the idea I've got)
3. How is str = #"Hi there!" different from
str = [[NSString alloc] initWithString:#"Hi there!"];
As I understand, you have to release str in aquired with second method, but not with first? If so, when does the first one get released? Which one is preferable (not minding the typing length)?
4. What is autorelease, if iphone has no garbage collection? I've noticed something called "an autorelease pool" being created in main.m. Is [myObject autorelease]; a way of adding myObject to the nearest wrapping "autorelease pool", which will release it? Basically, some magic to avoid releasing it yourself? Why use it?
Well, thats it for now. Thanks for any answers!
In Objective-C, it's possible to return an instance other than self from -init. Classes do this, for example, to enforce a singleton instance, or in the case of class clusters. NSNumber, for example, returns a subclass depending on the type of value passed to its initializer. So when you call [[NSNumber alloc] initWithLong:long_value], NSNumber's -initWithLong: initializer is called after NSNumber's +alloc, but a subclass of NSNumber may be returned to the oringial caller. Thus the pattern
self = [super init];
which reassigns self to the value of [super init] so that self points to the actual instance that [super init] returned. If +alloc or the super's init method fails, the result of [super init] may be nil. To avoid, side effects in the case of a failed initialization, the pattern then becomes
- (id) init {
if(self = [super init]) {
// do initialization of instance variables etc.
}
return self;
}
Note that you must return self (or nil or an other instance) from the init method. You should assign self to [super init] and you may check for nil before doing more work.
You may have to release the return value of a staic method. You should read the Cocoa memory management guide. The rule is generally quite simple: If the method you call has "new", "alloc", or "copy" in its signature, the result belongs to the caller and the caller must call -release on that instance or there will be a memory leak. Of course you should call -retain on anything else (i.e. not from an "alloc","new" or "copy" method) you want to keep a reference to and then call -release or -autorelease when you are done with that instance.
str = #"Hi there!", assuming str was declared as NSString *str; assigns the address of the string constant #"Hi there!" to the value of thestrvariable. You do not need to retain or release string constants.str = [[NSString alloc] initWithString:#"Hi there!"];allocates a new string instance. The value ofstrwill be the address of this instance. Each call ofstr = [[NSString alloc] initWithString:#"Hi there!"];again will allocate a new instance. So afterstr2 = [[NSString alloc] initWithString:#"Hi there!"];,str != str2, while afterstr2 = #"Hi There!", str==str2. See this answer as well.
-autorelease adds the receiver to the current NSAutoreleasPool. When the pool is drained (usually at the end of the current run loop iteration, or when the pool is manually drained), the pool calls -release on all instances in the pool. If this -release drops the retain count to 0, the object is deallocated (and -dealloc called) just as with any other -release. Using an autorelease pool is generally frowned upon on the iPhone because it may cause you to accumulate many unused instances in the pool before it is drained at the end of the run loop iteration. If you can use -release instead of -autorelease, you generally should. Again, see the Cocoa memory management guide for more info.
There is a school of thought that in most cases, allocating the self pointer is something that the system should do, and not the programmer.
Also, many people prefer to keep the main line of program flow as un-indented as possible. In which case the initialisation code could be re-written as:
- (id)init {
if (![super init]) {
return nil; // There is a problem so bail early.
}
// Initialisation code here.
return self
}
Will Shipley explains this much better than I do.
1: This check is to ensure that the super constructor returned a new object.
2: Static methods don't refer to an instance
3:
str = #"Hi there!"
This assigns the address of the constant string "Hi there!" to the pointer str
str = [[NSString alloc] initWithString:#"Hi there!"];
This allocates a string and copies "Hi There!" to it. This means that a) str is modifiable and b) needs to be deallocated when you are done with it.
calling
self = [super init];
May return nil if the superclass cannot initialize itself for some reason or other, including memory being unavailable, or certain prerequisites have not been met. If that is the case, you don't want to be trying to set variables of self, or set self as a delegate, or add self to an array, if self is nil.
The autorelease pool is something created upon every event the iPhone sends your application. It is created before any code runs, and released after all your code is done, for each event. Any objects that you call autorelease on will be put into the current autorelease pool. Any objects in the autorelease pool will be released as many times as they were added, after your code completes. In this way, you don't have to worry about who's responsible for releasing an object created by one method and returned to another method.
You can create your own autorelease pools as necessary.
str = [[NSString alloc] initWithString:#"Hi there!"];
This line creates a string that is not in an autorelease pool, so you have to release it manually. Simply writing
#"Hi there!";
returns a string that you don't have to worry about releasing. Extending your previous example:
str = [[[NSString alloc] initWithString:#"Hi there!"] autorelease];
would be another method of creating a string you don't need to worry about releasing.
One difference between garbage collection and autorelease pools is that garbage collection works with circular references. Using autorelease pools, you don't want to have two objects that retain each other and hope that once nothing else refers to them, they will go out of existence; they won't.
If self is nil after the super initialisation then you're probably out of memory. Your only reasonable course of action is to return nil and hope things get handled gracefully further up the stack.
Static methods aren't allowed allocate on the heap, therefore there's nothing to free.
In the first instance, the string is compiled into the data segment of your app and cannot be freed. In the second instance, you are allocating memory from the heap and copying your static string (from the data segment) into it.
It's simple garbage collection. As to why to use it, the simple answer is don't. It's not recommended to use autorelease on the iPhone due to limited resources.