Register FAQ / Rules Forum Spy Search Today's Posts Mark Forums Read
Go Back   MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Reply
 
Thread Tools Search this Thread Display Modes
Old Jun 23, 2008, 02:32 AM   #1
sujithkrishnan
macrumors 6502
 
Join Date: May 2008
Location: Bangalore
Send a message via Yahoo to sujithkrishnan
static object (memory management)

Hi all,

I my iPhone app, i am i am having a static object "staticCatalogObj" implemented as follows....
Code:
+(Catalog *)getCatalogObject
{
	if(staticCatalogObj == nil)
	{
		staticCatalogObj = [[Catalog alloc]init];
		staticCatalogObj.catalogDictionary = [[NSMutableDictionary alloc] init];
		staticCatalogObj.itemsArray = [[NSMutableArray alloc]init];
	
	}
	return staticCatalogObj;
}
I am calling this method in many view controllers to get the same object.
What all things i want to implement / and the necessary releasing statements i want to add to this part??

In many view controllers i have, i am getting this object by

Code:
Catalog localInstanceOfCatalog = [Catalog getCatalogInstance];
// modify the catalog localObject as per requirement...
[localInstanceOfCatalog release];
Is this enough from memory point of view???
sujithkrishnan is offline   0 Reply With Quote
Old Jun 23, 2008, 02:47 AM   #2
Sander
macrumors 6502
 
Join Date: Apr 2008
If you expect client code to release your object after they're done with it, shouldn't you add an extra retain each time you hand it out..?
Sander is offline   0 Reply With Quote
Old Jun 23, 2008, 03:06 AM   #3
Sbrocket
macrumors 65816
 
Sbrocket's Avatar
 
Join Date: Jun 2007
Location: /dev/null
The first part is the correct way to implement a singleton. You may also want to add the following to make sure that the more than one instance of the class cannot be created (if its only your own code, this doesn't matter as much, but its good practice for libraries and such).

Code:
+(id)alloc {
	NSAssert(sharedCatalogObj==nil,@"Attempted to allocate a second instance of a singleton.");
	return [super alloc];
}
In the second part, you're releasing an object that was never in your ownership. In other words, you're releasing it without retaining it first. You should remove that last release line as long as all that code is occurring within the same method.

If this catalog object is the same as the gigantic object your were talking about in the other thread, then you should consider other ways of accessing the data that won't result in you getting memory warnings all the time because of a single big object taking up all the available memory space.

---

Quote:
Originally Posted by Sander View Post
If you expect client code to release your object after they're done with it, shouldn't you add an extra retain each time you hand it out..?
Wrong solution to the problem. The "client code" (which I'm guessing is a reference to the 2nd block there) is incorrect in that it releases an object it never took ownership of. Taking ownership of an object that's not going to be released by the same code, as you suggest he do in the sharedObject method, just compounds the problem. You may get technically correct behavior, but that's bad coding practice to retain in one part of the code simply because a release is expected in a completely separate part. That would be completely unmaintainable.
__________________

Unibody MBP 15" | 2.53GHz | 4GB DDR3 | 320GB @ 7200RPM

Last edited by Sbrocket; Jun 23, 2008 at 03:11 AM.
Sbrocket is offline   0 Reply With Quote
Old Jun 23, 2008, 04:41 AM   #4
sujithkrishnan
Thread Starter
macrumors 6502
 
Join Date: May 2008
Location: Bangalore
Send a message via Yahoo to sujithkrishnan
Quote:
Originally Posted by Sbrocket View Post
The first part is the correct way to implement a singleton. You may also want to add the following to make sure that the more than one instance of the class cannot be created (if its only your own code, this doesn't matter as much, but its good practice for libraries and such).

Code:
+(id)alloc {
	NSAssert(sharedCatalogObj==nil,@"Attempted to allocate a second instance of a singleton.");
	return [super alloc];
}
In the second part, you're releasing an object that was never in your ownership. In other words, you're releasing it without retaining it first. You should remove that last release line as long as all that code is occurring within the same method.

If this catalog object is the same as the gigantic object your were talking about in the other thread, then you should consider other ways of accessing the data that won't result in you getting memory warnings all the time because of a single big object taking up all the available memory space.

---



Wrong solution to the problem. The "client code" (which I'm guessing is a reference to the 2nd block there) is incorrect in that it releases an object it never took ownership of. Taking ownership of an object that's not going to be released by the same code, as you suggest he do in the sharedObject method, just compounds the problem. You may get technically correct behavior, but that's bad coding practice to retain in one part of the code simply because a release is expected in a completely separate part. That would be completely unmaintainable.
Uff...
i am wondering why apple put memory management burden over the developer for iPhone rather having garbage collector for it....

My doubt is that i am having many localCatalogInstances in mnay of my classes, like

[CODE]
localCatalogForFistScreen = [Catalog getCatalogInstance];
localCatalogForSecondScreen = [Catalog getCatalogInstance];

Is all these add to increase in retainCount of the singleton object?
I thought in that way and thats why i made that release statement there in client who calls the method...
sujithkrishnan is offline   0 Reply With Quote
Old Jun 23, 2008, 04:46 AM   #5
sujithkrishnan
Thread Starter
macrumors 6502
 
Join Date: May 2008
Location: Bangalore
Send a message via Yahoo to sujithkrishnan
Quote:
Originally Posted by Sbrocket View Post
The first part is the correct way to implement a singleton. You may also want to add the following to make sure that the more than one instance of the class cannot be created (if its only your own code, this doesn't matter as much, but its good practice for libraries and such).

Code:
+(id)alloc {
	NSAssert(sharedCatalogObj==nil,@"Attempted to allocate a second instance of a singleton.");
	return [super alloc];
}
In the second part, you're releasing an object that was never in your ownership. In other words, you're releasing it without retaining it first. You should remove that last release line as long as all that code is occurring within the same method.

If this catalog object is the same as the gigantic object your were talking about in the other thread, then you should consider other ways of accessing the data that won't result in you getting memory warnings all the time because of a single big object taking up all the available memory space.

---



Wrong solution to the problem. The "client code" (which I'm guessing is a reference to the 2nd block there) is incorrect in that it releases an object it never took ownership of. Taking ownership of an object that's not going to be released by the same code, as you suggest he do in the sharedObject method, just compounds the problem. You may get technically correct behavior, but that's bad coding practice to retain in one part of the code simply because a release is expected in a completely separate part. That would be completely unmaintainable.
Yeah SB...

This is the object that i mentioned which want to keep it in memory for generating my all views.... All the relation between menus->categories->sub categories are represented in this object...

Eventhough i go for archiving (which i did) i want to load (unarchive) the catalogObject to generate my menus (tableViewControllers)...

Last edited by sujithkrishnan; Jun 23, 2008 at 05:06 AM.
sujithkrishnan is offline   0 Reply With Quote
Old Jun 23, 2008, 10:05 AM   #6
admanimal
macrumors 68040
 
Join Date: Apr 2005
Quote:
Originally Posted by sujithkrishnan View Post
Uff...
i am wondering why apple put memory management burden over the developer for iPhone rather having garbage collector for it....
Garbage collection requires more computation, which equals lower battery life. It can also result in less efficient memory usage (assuming the developer does proper memory management), which is bad for a device with limited memory.
admanimal is offline   0 Reply With Quote
Old Jun 23, 2008, 10:11 AM   #7
Sbrocket
macrumors 65816
 
Sbrocket's Avatar
 
Join Date: Jun 2007
Location: /dev/null
Quote:
Originally Posted by sujithkrishnan View Post
My doubt is that i am having many localCatalogInstances in mnay of my classes, like

Code:
localCatalogForFirstScreen = [Catalog getCatalogInstance];
localCatalogForSecondScreen = [Catalog getCatalogInstance];
Is all these add to increase in retainCount of the singleton object?
I thought in that way and thats why i made that release statement there in client who calls the method...
That local variable assignment alone isn't increasing the retain count of the singleton object, no.
__________________

Unibody MBP 15" | 2.53GHz | 4GB DDR3 | 320GB @ 7200RPM
Sbrocket is offline   0 Reply With Quote
Old Jun 23, 2008, 11:04 AM   #8
whooleytoo
macrumors 603
 
whooleytoo's Avatar
 
Join Date: Aug 2002
Location: Cork, Ireland.
Send a message via AIM to whooleytoo
As suggested elsewhere, perhaps the best place to allocate the Catalog object is in the alloc or init methods.

If you do it as you've done above, I'd suggest autoreleasing the Catalog object as you return it; or consistency reasons. The calling code than then retain it, as needed.
__________________
Mac <- Macintosh <- McIntosh apples <- John McIntosh <- McIntosh surname <- "Mac an toshach" <- "Son of the Chief"
whooleytoo is offline   0 Reply With Quote
Old Jun 23, 2008, 11:20 AM   #9
Sbrocket
macrumors 65816
 
Sbrocket's Avatar
 
Join Date: Jun 2007
Location: /dev/null
Quote:
Originally Posted by whooleytoo View Post
As suggested elsewhere, perhaps the best place to allocate the Catalog object is in the alloc or init methods.

If you do it as you've done above, I'd suggest autoreleasing the Catalog object as you return it; or consistency reasons. The calling code than then retain it, as needed.
Err, autoreleasing the singleton object in the sharedObject method? That wouldn't make any sense. The object is created with a retain count of 1 because of the alloc-init on the first call of sharedObject, and in the dealloc method the sharedObject should be released. That means that the singleton class has fulfilled its memory management obligation - it takes ownership of the object at creation, and releases ownership of the object on dealloc.

Here's my idea for solving your overarching problem:

You want to release the singleton object at some point to in the execution to save memory, so create a method like this that you can call in your didReceiveMemoryWarning: methods.

Code:
+(void)destroySingleton {
	if (sharedObj) {
		[self saveSingletonDataToDisk]; // Some method to save all that data to disk
		[sharedObj release];
		sharedObj = nil;
	}
}
Of course, you'd want to add something to your init to load the saved data again from disk. This would mean that the singleton data could be released when not needed (say, on a memory warning sent to a view controller) and created again when needed.

The correct way to use the singleton object in the rest of the code, then, would not be to retain a reference to it in your other classes but to access [MyObjectClass sharedObject] whenever you wanted to use it for some reason. That way if the singleton object was currently residing in memory, it would simply return the pointer to it, and if it didn't exist yet or had been released because of a memory warning it would be loaded from disk again, created, and returned.

The key part here, of course, is to not retain references to the singleton in other parts of your code so that when you call [MyObjectClass destroySingleton] it is, in fact, released and not leaked. That would be bad, and would pretty much result in worse memory performance than before. Of course, you should try to minimize how often you access the shared object since caching and loading it all the time is also bad. I'm not sure exactly what you're storing in there, but try to use it as little as possible or you're not going to realize any benefits with this.

If you need to access it constantly, then you'll probably want to ignore everything I said and find some other solution. To be honest, though, I can't see why you need to keep so much data in memory constantly such that you're getting memory warnings all the time. What exactly are you storing in there that's taking up so much memory, anyway?

This would seem, to me at least, to be the best way to handle your memory problem sujithkrisnan.
__________________

Unibody MBP 15" | 2.53GHz | 4GB DDR3 | 320GB @ 7200RPM
Sbrocket is offline   0 Reply With Quote
Old Jun 24, 2008, 01:19 AM   #10
sujithkrishnan
Thread Starter
macrumors 6502
 
Join Date: May 2008
Location: Bangalore
Send a message via Yahoo to sujithkrishnan
Quote:
Originally Posted by Sbrocket View Post
Err, autoreleasing the singleton object in the sharedObject method? That wouldn't make any sense. The object is created with a retain count of 1 because of the alloc-init on the first call of sharedObject, and in the dealloc method the sharedObject should be released. That means that the singleton class has fulfilled its memory management obligation - it takes ownership of the object at creation, and releases ownership of the object on dealloc.

Here's my idea for solving your overarching problem:

You want to release the singleton object at some point to in the execution to save memory, so create a method like this that you can call in your didReceiveMemoryWarning: methods.

Code:
+(void)destroySingleton {
	if (sharedObj) {
		[self saveSingletonDataToDisk]; // Some method to save all that data to disk
		[sharedObj release];
		sharedObj = nil;
	}
}
Of course, you'd want to add something to your init to load the saved data again from disk. This would mean that the singleton data could be released when not needed (say, on a memory warning sent to a view controller) and created again when needed.

The correct way to use the singleton object in the rest of the code, then, would not be to retain a reference to it in your other classes but to access [MyObjectClass sharedObject] whenever you wanted to use it for some reason. That way if the singleton object was currently residing in memory, it would simply return the pointer to it, and if it didn't exist yet or had been released because of a memory warning it would be loaded from disk again, created, and returned.

The key part here, of course, is to not retain references to the singleton in other parts of your code so that when you call [MyObjectClass destroySingleton] it is, in fact, released and not leaked. That would be bad, and would pretty much result in worse memory performance than before. Of course, you should try to minimize how often you access the shared object since caching and loading it all the time is also bad. I'm not sure exactly what you're storing in there, but try to use it as little as possible or you're not going to realize any benefits with this.

If you need to access it constantly, then you'll probably want to ignore everything I said and find some other solution. To be honest, though, I can't see why you need to keep so much data in memory constantly such that you're getting memory warnings all the time. What exactly are you storing in there that's taking up so much memory, anyway?

This would seem, to me at least, to be the best way to handle your memory problem sujithkrisnan.

Thanks alot for the detailed explntn...

I am creating a shopping application, which comprising 20 shops, having around 900 items as product...
All these are gettign n=by parsing an xml at a URL...
I want to keep this all shop -product structure to generate the navigation menu for user to navigate..

I am trying to minimize the server-hitting, so i am downlaoding all the shop-products to device...

Okie, i will try some other design....
Thanks again..
sujithkrishnan is offline   0 Reply With Quote

Reply
MacRumors Forums > Apple Systems and Services > Programming > Mac Programming

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Similar Threads
thread Thread Starter Forum Replies Last Post
Optimizing memory management activate OS X 10.8 Mountain Lion 15 Jun 23, 2013 08:07 PM
Memory management is confusing! nashyo iPhone/iPad Programming 1 Mar 2, 2013 07:33 PM
Is Linux better at memory management than XP? RedCroissant Windows, Linux & Others on the Mac 5 Feb 5, 2013 12:20 PM
Improved memory management brijazz OS X 10.8 Mountain Lion 18 Jul 28, 2012 12:17 PM
Memory Management StuffMattSays Mac OS X 10.7 Lion 12 Jul 3, 2012 02:48 PM

Forum Jump

All times are GMT -5. The time now is 03:19 AM.

Mac Rumors | Mac | iPhone | iPhone Game Reviews | iPhone Apps

Mobile Version | Fixed | Fluid | Fluid HD
Copyright 2002-2013, MacRumors.com, LLC