does [NSFont systemFontOfSize] memory needs to be released - objective-c

I am trying to lower the footprint of memory my application uses at runtime....
In the standard usage to get a font based on system font size the api is used as font = [NSFont systemFontOfSize]
+ (NSFont *)systemFontOfSize:(CGFloat)fontSize; // Aqua System font
As per my understanding that the font will be freed by the autorelease pool, First I need to confirm that this understating is correct?
If this is correct, then if I have a drawWithFrame function where I am using this every time I draw a cell. Should I not release it there? and would increasing the memory footprint of the application, since the fonts would be freed when the applications autorelease pool is called?
Now is again this understanding is correct? There are 2 approaches
Find a way to release NSFont
Put a NSAutoReleasePool *pool. alloc / release there itself in draw with frame
What do you guys suggest?

The function name systemFontOfSize: doesn't begin with any of the magic keywords "alloc", "new", "copy", or "mutableCopy", so you aren't responsible for releasing what it returns. See the Cocoa basic memory management rules for details.

I'm not use to dealing with Font so I might be out of the way.
But to me if you frequently need and object, I would cache it in a property.
Creating and deletion is more expensive than reading a property.
And if this is a key feature of your class, I would event create it in the init of my class.
That would save the unnecessary test to see if it already exist.

You are correct on both items. By convention, all named initializers return autoreleased objects. Since you (scope of drawWithFrame) did not excplicitly allocate font you are not responsible for releasing it. Like you also suggested, this can be optimizated by putting an autorelease pool around it.
Wether or not the benefit is worth the extra typing work of the coder is debatable.

As with most non-"init" methods that return an object ("copy" is an exception that pops to mind) the object returned by systemFontOfSize is autoreleased and so it will be released at some point in the (very near) future.
If you want to use the object pointed to by your variable "font" outside of the local scope you should retain it and release it when it's no longer needed (or before being replaced by another font)
Edit: I just reread realized you're creating the font every time so the 2nd paragraph isn't so relevant to your question, but anyway, unless the font is something that has to change many times a second I'd consider creating the font object outside the drawrect method. I don't know how much of a practical effect this specifically would have on your current FPS/responsiveness but it's generally good to get used to not doing stuff such as object creation redundantly multiple times in loops etc.

Related

Proper time to use the retain message?

thanks for viewing this post, it'd be great if you guys can help me out. I've been doing some objective-c and learned about the objective-c way of memory management, like making sure to call release whenever I own the object, when to call autorelease, etc. I also do not want to use ARC or the newly introduced GC because I like to manage my own memory, I plan to advance later on into iOS development, and I know it's a good practice to manage my own memory. But there's still one small detail that I seem to have hit a brick wall in. It has to do with sending objects the -retain message. I learned that sending the -retain message increments the reference count by 1. But would this be an appropriate time to send -retain? :
- (void) setName : (NSString* ) theName
{
// name is an instance variable of type NSString
[theName retain]; // Must release this
name = [theName copy]; // Must release this in dealloc
[theName release]; // decrement the reference count because of retain
}
Should I call retain here so that I own the argument temporarily and ensure it doesnt'
get released somehow before I get to use it?
Any help would be appreciated! Thanks!
No. You the object supplied as an argument to the method will generally be around until your method returns. You don't need the retain messages there. You copy the string here to keep it around after the method returns.
This is documented in Apple's Documentation on this page in the "Avoid Causing Deallocation of Objects You’re Using" Section. Specifically:
Cocoa’s ownership policy specifies that received objects should
typically remain valid throughout the scope of the calling method. It
should also be possible to return a received object from the current
scope without fear of it being released. It should not matter to your
application that the getter method of an object returns a cached
instance variable or a computed value. What matters is that the object
remains valid for the time you need it.
As an aside you really should consider using ARC. Its not good practise to manage your own memory. No matter how good one can be at managing their own memory the LLVM compiler is still better. Managing your own memory will lead to hard to troubleshoot issues caused only by yourself. It is an extra level of cognitive load that you really don't have to deal with and, when you finally let manual memory management go, you will breathe a sigh of relief at all the mental overhead you didn't even know was there.

What do you think about this code in Objective-C that iterates through retain count and call release every iteration?

I'm still trying to understand this piece of code that I found in a project I'm working on where the guy that created it left the company before I could ask.
This is the code:
-(void)releaseMySelf{
for (int i=myRetainCount; i>1; i--) {
[self release];
}
[self autorelease];
}
As far as I know, in Objective-C memory management model, the first rule is that the object that allocates another object, is also responsible to release it in the future. That's the reason I don't understand the meaning of this code. Is there is any meaning?
The author is trying to work around not understand memory management. He assumes that an object has a retain count that is increased by each retain and so tries to decrease it by calling that number of releases. Probably he has not implemented the "is also responsible to release it in the future." part of your understanding.
However see many answers here e.g. here and here and here.
Read Apple's memory management concepts.
The first link includes a quote from Apple
The retainCount method does not account for any pending autorelease
messages sent to the receiver.
Important: This method is typically of no value in debugging memory
management issues. Because any number of framework objects may have
retained an object in order to hold references to it, while at the
same time autorelease pools may be holding any number of deferred
releases on an object, it is very unlikely that you can get useful
information from this method. To understand the fundamental rules of
memory management that you must abide by, read “Memory Management
Rules”. To diagnose memory management problems, use a suitable tool:
The LLVM/Clang Static analyzer can typically find memory management
problems even before you run your program. The Object Alloc instrument
in the Instruments application (see Instruments User Guide) can track
object allocation and destruction. Shark (see Shark User Guide) also
profiles memory allocations (amongst numerous other aspects of your
program).
Since all answers seem to misread myRetainCount as [self retainCount], let me offer a reason why this code could have been written: It could be that this code is somehow spawning threads or otherwise having clients register with it, and that myRetainCount is effectively the number of those clients, kept separately from the actual OS retain count. However, each of the clients might get its own ObjC-style retain as well.
So this function might be called in a case where a request is aborted, and could just dispose of all the clients at once, and afterwards perform all the releases. It's not a good design, but if that's how the code works, (and you didn't leave out an int myRetainCount = [self retainCount], or overrides of retain/release) at least it's not necessarily buggy.
It is, however, very likely a bad distribution of responsibilities or a kludgey and hackneyed attempt at avoiding retain circles without really improving anything.
This is a dirty hack to force a memory release: if the rest of your program is written correctly, you never need to do anything like this. Normally, your retains and releases are in balance, so you never need to look at the retain count. What this piece of code says is "I don't know who retained me and forgot to release, I just want my memory to get released; I don't care that the others references would be dangling from now on". This is not going to compile with ARC (oddly enough, switching to ARC may just fix the error the author was trying to work around).
The meaning of the code is to force the object to deallocate right now, no matter what the future consequences may be. (And there will be consequences!)
The code is fatally flawed because it doesn't account for the fact that someone else actually "owns" that object. In other words, something "alloced" that object, and any number of other things may have "retained" that object (maybe a data structure like NSArray, maybe an autorelease pool, maybe some code on the stackframe that just does a "retain"); all those things share ownership in this object. If the object commits suicide (which is what releaseMySelf does), these "owners" suddenly point to bad memory, and this will lead to unexpected behavior.
Hopefully code written like this will just crash. Perhaps the original author avoided these crashes by leaking memory elsewhere.

Calling Methods On Released Objects

I think there is something I'm missing about memory management. Here's the code:
NSString *string = #"foo";
[string release];
NSLog(#"%#", string);
I expect to get a memory error with that code, but instead the code is ran without errors. I noticed this as I was following a book and a scrollView was released before setting properties and adding a subView (but after being inserted in the main view).
My question is, when are objects really deallocated? Would this e considered good coding style?
This works because your string variable is pointing to a constant string that has been compiled into your application. retaining it does nothing and releaseing it does nothing as well. It exists in static memory, and it will only be destroyed when your program is unloaded from memory.
If you alloc, retain or copy an object, it is your responsibility to release it. Everything else is dealt with by the system and will be flushed with the auto release pool.
There are way too many memory management questions on SO already, have a quick look around to get yourself acquainted https://stackoverflow.com/search?q=memory+management+iphone
[edit]
Probably the most important part of your question that you need to understand is in your second last paragraph:
I was following a book and a scrollView was released before setting properties and adding a subView (but after being inserted in the main view).
I haven't seen this code but it is likely that you added the scrollView to your UIView instance. In these cases, the receiving view always retain its subview(s) so you are free to release it.
Once the UIView instance is released it wil also send a release message to all its subviews, which includes the scrollView.
Makes sense?
Sending a message to a deallocated object is undefined behavior. You might get a memory error, you might end up sending a message to another object, you might end up sending an message to a phantom version of the former object — it all depends on implementation details and details of the environment at runtime that are mostly out of your control. In this specific case, you're running into the implementation detail that NSString constants are immortal.
As for specifically when an object will be deallocated, that's also an implementation detail. If you don't own an object and don't have a reasonable guarantee that it will still be around (e.g. you just got it by doing [someArrayYouOwn objectAtIndex:0]), you should not be dealing with it.
The best policy: Just don't send messages to objects you no longer own. Follow the memory management rules.

How should I memory manage objects returned by instance methods?

Plenty of Objective-C classes return objects. Statements like [[instanceOfNSWhatever objectForKey:aKey] stringValue], for instance, appear all over my (and hopefully everyone else's code).
How am I supposed to memory manage these "intermediate" objects?
Were they just created or did they always exist?
Can I retain them, and if I release the object that created them, will they be released as well?
Are they autoreleased?
What if I run [instanceOfNSWhatever stringValue] a million times in a loop? Can I dispose of all those NSStrings as needed?
I'm still learning ObjC, and while I've been good at balancing my retain counts overall, I'm definitely lacking some understanding about how these methods work. Can anyone fill me in?
You've probably already read this section of Apple's docs about memory management, but I'll point you to the section about the Object Ownership Policy just in case. You are only responsible for managing the memory of objects you "own". To quote the docs:
You own any object you create.
You "create" an object using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy).
If you own an object, you are responsible for relinquishing ownership when you have finished with it. [ie: release]
If you do not own an object, you must not release it.
The "Simple Examples" section of those docs provide good elaboration, but to put the points above in the context of your specific questions:
How am I supposed to memory manage these "intermediate" objects?
The good news is: you don't. Ignore the the memory management aspect of the "intermediate" objects in your example.
Were they just created or did they always exist?
They may have always existed, or they may have just been created. The beauty of objective-c is that you, as a consumer of those objects, don't have to care.
Can I retain them, and if I release the object that created them, will they be released as well?
You don't need to retain them if you're just passing them on to some other function, or using them as intermediate values yourself in your own calculations within the function. Say, for example, that you're returning the stringValue from your example function to someone else. There's no point in retaining it just to return it.
If you DO happen to retain it, then yes, you are responsible for issuing a corresponding release message as some point. You might, for example, retain the stringValue from your example if you want to hold on to that value as a property in your own instance. Objective-C uses reference counting. If you need that object to stick around for a long time, you must retain it so that someone else's release message doesn't cause it to vanish if the retain count falls to 0.
Are they autoreleased?
Depends. Let's say you ask for a string from instanceOfNSWhatever. If instanceOfNSWhatever has to create that string just special for you (in order to service your request), but doesn't otherwise care about that string, then yes... instanceOfNSWhatever probably put that string into the autorelease pool. If the string was already a property of instanceOfNSWhatever and it was just sending it to you in response to your request, then no, it probably wasn't autoreleased.
Again, the beauty is: you don't know and don't need to care. Since instanceOfNSWhatever created the string, it is responsible for managing it. You can ignore the memory management unless you add to the string by sending it a retain message.
What if I run [instanceOfNSWhatever stringValue] a million times in a loop? Can I dispose of all those NSStrings as needed?
No need. Again... stringValue isn't yours to manage because you didn't create it. As a technical note, if instanceOfNSWhatever really did have to create 1 million copies of stringValue to service your 1 million calls, it probably put them all in an autorelease pool, which would be drained at the end of the current cocoa event loop. Fortunately, unless you send each of those stringValue objects a retain message, you can gleefully ignore the memory management question here.
You basically manage all your memory according to the Memory Management Programming Guide for Cocoa. In short, however, you basically only need to worry about objects that you "own". You own an object if you create it (in Cocoa, you create an object by specifically allocating it using alloc or copying it using copy or one of their derivatives). If you own an object, you are responsible for releasing it when you are finished with it.
Any other object is, therefore, not owned by you. If you need to use such an object for any extended period (for example, outside the scope in which you received it), you need to specifically take ownership of the object by either sending it a retain message or copying it.
To answer your last question, if you are creating a lot of temporary objects in a loop or some other way, you can create your own autorelease pools. See the documentation for NSAutoreleasePool for more information about using them. Please note, however, that you should really only do this after you've profiled your application and found that it is using too much memory and would benefit from this kind of optimization.
Finally, if you are creating and releasing a lot of heavy objects and don't want to rely on autorelease pools, you can specifically allocate and initialize them and then make sure to release them on your own as soon as you're finished with them. Most objects that have convenience creators have similar initializers for creating the object specifically.
When working on the iPhone/iPod Touch, the autorelease objects are released when your application exits. This may be what you don't want. Especially when working with images or large chunks of data. To insure large pools of memory that are tagged autorelease get released sooner, create local autorelease pools. Like this:
NSAutoreleasePool *localPool = [[NSAutoreleasePool alloc] init];
-- do something that creates large autorelease memory blocks --
[localPool drain];
If you don't do this, you will find your application exiting unexpectedly.
I'll tell you a simple rules I wish I'd known when I first started Objective-C :)
If an method contains the words "alloc" or "copy" then you must [release] the object when finished.
If a method does not contain these words, you must [retain] it for it to remain valid outside of your function.
If you call [retain] you must later call [release] when finished.
This covers practically all you need to know about the basics of memory management.
ObjC makes heavy use of what are known as "auto release" pools. Objects returned from non alloc/copy functions are placed into these pools and automatically freed after your function exists.
That is why you do not need to release the results of something like [obj stringValue].

Instance caching in Objective C

I want to cache the instances of a certain class. The class keeps a dictionary of all its instances and when somebody requests a new instance, the class tries to satisfy the request from the cache first. There is a small problem with memory management though: The dictionary cache retains the inserted objects, so that they never get deallocated. I do want them to get deallocated, so that I had to overload the release method and when the retain count drops to one, I can remove the instance from cache and let it get deallocated.
This works, but I am not comfortable mucking around the release method and find the solution overly complicated. I thought I could use some hashing class that does not retain the objects it stores. Is there such? The idea is that when the last user of a certain instance releases it, the instance would automatically disappear from the cache.
NSHashTable seems to be what I am looking for, but the documentation talks about “supporting weak relationships in a garbage-collected environment.” Does it also work without garbage collection?
Clarification: I cannot afford to keep the instances in memory unless somebody really needs them, that is why I want to purge the instance from the cache when the last “real” user releases it.
Better solution: This was on the iPhone, I wanted to cache some textures and on the other hand I wanted to free them from memory as soon as the last real holder released them. The easier way to code this is through another class (let’s call it TextureManager). This class manages the texture instances and caches them, so that subsequent calls for texture with the same name are served from the cache. There is no need to purge the cache immediately as the last user releases the texture. We can simply keep the texture cached in memory and when the device gets short on memory, we receive the low memory warning and can purge the cache. This is a better solution, because the caching stuff does not pollute the Texture class, we do not have to mess with release and there is even a higher chance for cache hits. The TextureManager can be abstracted into a ResourceManager, so that it can cache other data, not only textures.
Yes, you can use an NSHashTable to build what is essentially a non-retaining dictionary. Alternatively, you can call CFDictionaryCreate with NULL for release and retain callbacks. You can then simply typecast the result to a NSDictionary thanks to tollfree bridging, and use it just like a normal NSDictionary except for not fiddling with retain counts.
If you do this the dictionary will not automatically zero the reference, you will need to make sure to remove it when you dealloc an instance.
What you want is a zeroing weak reference (it's not a "Graal of cache managing algorithms", it's a well known pattern). The problem is that Objective C provides you with zeroing weak references only when running with garbage collection, not in manual memory managed programs. And the iPhone does not provide garbage collection (yet).
All the answers so far seem to point you to half-solutions.
Using a non-reataining reference is not sufficient because you will need to zero it out (or remove the entry from the dictionary) when the referenced object is deallocated. However this must be done BEFORE the -dealloc method of that object is called otherwise the very existence of the cache expose you to the risk that the object is resurrected. The way to do this is to dynamically subclass the object when you create the weak reference and, in the dynamically created subclass, override -release to use a lock and -dealloc to zero out the weak reference(s).
This works in general but it fails miserably for toll-free bridged Core Foundation objects. Unfortunately the only solution, if you need to to extend the technique to toll-free bridged objects, requires some hacking and undocumented stuff (see here for code and explanations) and is therefore not usable for iOS or programs that you want to sell on the Mac App Store.
If you need to sell on the Apple stores and must therefore avoid undocumented stuff, your best alternative is to implement locked access to a retaining cache and then scavenge it for references with a current -retainCount value of 1 when you want to release memory. As long as all accesses to the cache are done with the lock held, if you observe a count of 1 while holding the lock you know that there's no-one that can resurrect the object if you remove it from the cache (and therefore release it) before relinquishing the lock.
For iOS you can use UIApplicationDidReceiveMemoryWarningNotification to trigger the scavenging. On the mac you need to implement your own logic: maybe just a periodical check or even simply a periodical scavenging (both solutions would also work on iOS).
I've just implemented this kind of thing by using an NSMutableDictionary and registering for UIApplicationDidReceiveMemoryWarningNotification. On a memory warning I remove anything from the dictionary with a retainCount of 1...
Use [NSValue valueWithNonretainedObject:] to wrap the instance in an NSValue and put that in the dictionary. In the instance dealloc method, remove the corresponding entry from the dictionary. No messing with retain.
My understanding is that you want to implement the Graal of cache managing algorithms: drop items that will no longer be used.
You may want to consider other criteria, such as dropping the least recently requested items.
I think the way I would approach this is to maintain a separate count or a flag somewhere to indicate if the object in the cache is being used or not. You could then check this when you're done with an object, or just run a check every n seconds to see if it needs to be released or not.
I would avoid any solution involving releasing the object before removing it from the dictionary (using NSValue's valueWithNonretainedObject: would be another way to accomplish this). It would just cause you problems in the long run.