In my code, I use a singleton object as a central point in my app to load and cache images the app frequently needs, so I don't have to do resource-intensive memory allocation each time I load an image.
But there are times during the execution of my app where memory usage gets intense and I would like to release the cached image data. Currently, I'm just releasing the UIImage instances from my singleton when I get a memory warning.
I would prefer, however, to be able to release the entire singleton object. Is that possible? If so, how?
Of course it is. Although it's rather likely that the memory usage of this object is negligible compared to the images.
By the nature of a singleton, you need to have an accessor for it, where you will create it if it does not currently exist:
+ (MySingletonClass*) mySingleton
{
if ( mySingleton == nil )
{
mySingleton = [[MySingletonClass alloc] init];
}
return mySingleton;
}
You just need to add another that you call when you want to destroy it:
+ (void) destroyMySingleton
{
[mySingleton release];
mySingleton = nil;
}
If you keep references to it around elsewhere you'll have trouble; don't do that. If you access from multiple threads you'll need to synchronize. Otherwise, it's pretty straightforward -- the getter will recreate when you next need it.
Here's an example of a singleton accessor for the OpenAL code I'm using.
// Eric Wing. Singleton accessor. This is how you should ALWAYS get
// a reference to the sound controller. Never init your own.
+ (OpenALSoundController*) sharedController
{
static OpenALSoundController* shared_sound_controller;
#synchronized(self)
{
if (nil == shared_sound_controller)
{
shared_sound_controller = [[OpenALSoundController alloc] init];
}
}
return shared_sound_controller;
}
OpenAL takes a while to load up so keeping one instance around is exactly what I need. With more than one thread in play (not my situation currently but I want my code to be ported to situations where this is the case) I put a lock on self. #synchronized(self) does exactly that.
Now I allocated the memory so I'm responsible for releasing it. I could call [shared_sound_controller autorelease] in the +sharedController accessor method but this may release the controller early, particularly when I have more than one thread and I call the accessor for the first time in a thread that's not the main thread.
Any object you create you can just release at any time. (Presuming you create it and set it's properties.)
self.myObject = [[myObjectClass alloc] init];
// do something with the object
[self.myObject release]; // anytime that you are not using the object
self.myObject = nil; // will also work if you've set the #property (retain, nonatomic)
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.
i am new in ObjC and iPhone.
I downloaded an example of data sharing between multiple views. The basic approach is to create an data model object in the base UIApplication and get/set data from/to it. So in the init method i saw the following code:
- (id) init;
{
self.theAppDataObject = [[ExampleAppDataObject alloc] init];
[theAppDataObject release];
return [super init];
}
And after that, using delegate we can access this object.
id theDelegate = (id) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
So, my question is in the first code example. Why do we need to alloc memory for the theAppDataObject object, and immediately after that - release the object? Why don't we get nil when accessing this object later?
10x
I assume theAppDataObject is declared as #property (retain). Therefore, when setting the object by doing self.theAppDataObject (or [self setTheAppDataObject:]), this property will retain the ExampleAppDataObject. Therefore, you can release it afterwards.
When you alloc and init the ExampleAppDataObject, it's retain count goes up to 1. When you set the AppDataObject to this ExampleAppDataObject, it sends retain to it, so the retain count goes up to 2. You can then release your own ownership of the object; it won't get deallocated because theAppDataObject still has ownership.
If that makes sense.
That depends on how theAppDataObject property is defined.
If it provides a retaining setter-accessor the retain count of the appDataObject will flip to 2, one more than needed here.
So release one of it.
Better and more understandable way would be to write
if ( (self = [super init]) ) {
ExampleAppDataObject *myAppDataObject = [[ExampleAppDataObject alloc] init];
self.theAppDataObject = myAppDataObject;
[myAppDataObject release];
}
return self;
Iphone uses reference count based memory management model..See this tutorial first and then apple's technical documentation... theAppDataObject is a property (see the use of self. theAppDataObject) which should be retained for the above code to work..Any object which is retained should have a bonus plus 1 retain count...An object only gets released when its retain count gets to zero..
first things first: that code sample is terrible.
- (id) init
{
// assign self. super may return another address
self = [super init];
// then check for nil
if (self != nil) {
// then assign the ivar directly because you should
// not invoke methods of partially constructed objects
theAppDataObject = [[ExampleAppDataObject alloc] init];
}
// then return the address super returned
return self;
}
now for your questions:
Why do we need to alloc memory for the theAppDataObject object, and immediately after that - release the object?
self.theAppDataObject calls through the setter, which retains, copies, or assigns theAppDataObject. in this case, we could assume it is highly likely to be retained.
Why don't we get nil when accessing this object later?
release does not set a pointer to nil. it sends a message to the object which then decrements the retain count (in the typical case). what you might have expected in this case is an object which has been deallocated. that does not happen when the argument is retained because the reference count does not reach zero in the program you have shown. the object is still alive because it's been retained and the address of the object stored when the setter (self.theAppDataObject = arg) is called.
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.
This is an example straight from Apple's documentation -
#implementation MyClass
- (id)initWithString:(NSString *)aName
{
self = [super init];
if (self) {
name = [aName copy];
}
return self;
}
+ (MyClass *)createMyClassWithString: (NSString *)aName
{
return [[[self alloc] initWithString:aName] autorelease];
}
#end
As I would be creating a new MyClass Object in each case anyway, I want to know why I might use the Class Method createMyClassWithString:aName instead of the Instance Method initWithString:aName
Thanks
I always use the class method where possible because it results in less verbose code and if you are simply going to return the object to the caller you'd have to autorelease it anyway, if you obtained it with alloc.
The advice from Apple was poorly worded, in my opinion. People seem to be taking it as a blanket ban on autorelease. That's simply not the case. You just have to be mindful that autorelease comes withy a memory price, but it is not as high as you might think. Each runloop event except timer events comes with a new autorelease pool that gets drained on return to the runloop. So if you know the method is going to be quick there's no problem. Also, if an object is going to outlive the current event, there's no issue because the overhead ofd an object in an autorelease pool is quite small and draining the pool won't dealloc the object anyway.
The only case where you need to be careful about putting objects indiscriminately in the autorelease pool is where you have intensive processing creating lots of temporary autoreleased objects. You can relieve the pressure of these methods by creating autorelease pools and draining them as you go along. e.g.
while(someCondition)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
// intensive processing
[pool drain];
}
The only reason is readable and beautiful code...
In addition, in your example the class method returns an autoreleased instance...
The short, unhelpful answer would be: where is makes sense. Neither is more correct; neither is wrong.
An example might be more use. I would use the class method if I was returning the value from a method:
- (MyClass*) doStuff {
MyClass* retv = [MyClass createMyClassWithString:#"Simon says"];
[retv someOtherMethod];
return retv;
}
By convention you return autoreleased objects, so using the class method results in slightly less typing.
I have a class that contains a few instance methods which need to be called from another class. I know how to do that -
TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];
[myTimeFormatter formatTime:time];
However, I don't want to have to alloc and init TimeFormatter every time I need to call one of its methods. (I need to call TimeFormatter's methods from various methods in another class).
I tried putting
TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];
"by itself", or not in any blocks, but when I compile, I get an "initializer element is not constant" error.
Any input is greatly appreciated!
You can use the singleton pattern. You can read more about it here.
Specifically, you'd do something like:
static TimeFormatter* gSharedTimeFormatter = nil;
#implementation TimeFormatter
+ (TimeFormatter*)sharedTimeFormatter {
if (!gSharedTimeFormatter) {
#synchronized(self) {
if (!gSharedTimeFormatter) {
gSharedTimeFormatter = [[TimeFormatter alloc] init];
}
}
}
return gSharedTimeFormatter;
}
...
#end
Notice that we check if the variable is null, and if it is, we take a lock, and check again. This way, we incur the locking cost only on the allocation path, which happens only once in the program. This pattern is known as double-checked locking.
However, I don't want to have to alloc and init TimeFormatter every time I need to call one of its methods. (I need to call TimeFormatter's methods from various methods in another class).
I think it's worth clarifying some OOP terminology here.
The reason you need to alloc and init TimeFormatter is because your methods are instance methods. Because they're instance methods, you need an instance, and that's what alloc and init provide. Then you call your methods on (send messages to) the instance ([myTimeFormatter formatTimeString:…]).
The advantage of allowing instances is that you can keep state and settings in each instance, in instance variables, and make the latter into publicly-visible properties. Then you can deliberately have multiple instances, each having its own settings configured by whatever's using that instance.
If you don't need that functionality, you don't need to make these instance methods. You can make them class methods or even C functions, and then you don't need a TimeFormatter instance. With class methods, you send messages directly to the class ([TimeFormatter formatTimeString:…]).
And if you do want settings shared among all instances (and you don't have any state to keep), then you're right that you can just have one instance—a singleton.
The reason for that parenthesis is that shared state is bad, especially if two threads may use the time formatter concurrently. (For that matter, you could say that about settings, too. What if one thread wants seconds and the other doesn't? What if one wants 24-hour and the other wants 12-hour?) Better to have each thread use its own time formatter, so that they don't get tripped up by each other's state.
(BTW, if TimeFormatter is the actual name of your class: You are aware of NSDateFormatter, right? It does let you only format/parse the time.)
Here's a detail example of a sharedMethod. Credit goes here
#implementation SearchData
#synthesize searchDict;
#synthesize searchArray;
- (id)init {
if (self = [super init]) {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"searches.plist"];
searchDict = [[NSDictionary alloc] initWithContentsOfFile:finalPath];
searchArray = [[searchDict allKeys] retain];
}
return self;
}
- (void)dealloc {
[searchDict release];
[searchArray release];
[super dealloc];
}
static SearchData *sharedSingleton = NULL;
+ (SearchData *)sharedSearchData {
#synchronized(self) {
if (sharedSingleton == NULL)
sharedSingleton = [[self alloc] init];
}
return(sharedSingleton);
}
#end
A very nice, and easy, way to setup a Singleton is to use Matt Gallager's SYNTHESIZE_SINGLETON_FOR_CLASS.
It sounds like you want to make TimeFormatter a singleton, where only one instance can be created. Objective-C doesn't make this super easy, but basically you can expose a static method that returns a pointer to TimeFormatter. This pointer will be allocated and initialized the first time in, and every time after that same pointer can be used. This question has some examples of creating a singleton in Objective-C.
You are trying to declare your variable outside the class? If to do it the way you want to do it you gotta declare it as static so
static TimeFormatter *myFormatter=...
From the name of the class though i dont see why you would wnat to keep one instance of your class... you can also do this with a singleton as described above, that is if you want to keep one instance of your class for the app as a whole.