Memory retain and release - iphone

I wanted to know that if I am doing correctly, regarding retain and release of digitbutton reference down below. In the book "Programming in Objective C by Stephen Kochan", it says in one section with different example that like digitbutton is holding reference to same object that sender is holding, so in between sender may get released elsewhere and then I would be calling currenttitle method on deallocated digitbutton, if that is the case.
So here I called retain on digitbutton and after its use I called release on it. Well, the example maybe not genuine for this purpose but is this concept valid? Should I make practice to retain objects like in example below?
I am not experienced in writing managed codes.
- (IBAction)clickDigit:(id)sender {
UIButton *digitButton = (UIButton*)sender;
[digitButton retain];
NSLog(#"%#",[digitButton currentTitle]);
[[self displayOutput] setText:[digitButton currentTitle]];
[digitButton release];
}
Update
Yes, the example was wrong; let's say if instead of id sender there is NSString and instead of UIButton, same NSString, and return type is just void. Then do I have to retain sender NSString for safety in case someone holding its reference releases it.
Note: I am not using ARC.

You dont need to retain & release it.
You can do like this
- (IBAction)clickDigit:(UIButton *)sender
{
NSLog(#"%#",[sender currentTitle]);
[[self displayOutput] setText:[sender currentTitle]];
}

What you're doing in clickDigit: is unnecessary.
Instead of me explaining why it is unnecessary, I will point you directly to where I learned proper memory management techniques: Advanced Memory Management Programming Guide

Related

Objective-C: detect if an object has no more holders

I use an NSMutableArray as a "Window Manager" to store all my NSView objects, I send it like
[windowManager addObject:self];
right after ViewDidLoad of each NSView;
the question is, how can I detect on my "windowManager" NSMutableArray if it stores objects that has been called to release (and windowManager is the only one holding their instance)?
After I call a release upon an one of these NSViews and turn
SomeNSViewPointer = nil;
, I also need the WindowManager to check the above.
When you do this:
[someNSViewPointer release];
SomeNSViewPointer = nil;
Do this instead:
[someNSViewPointer release];
[windowManager removeObject: someNSViewPointer];
SomeNSViewPointer = nil;
I would have to question why you are storing two references to your view though. I think your design needs reviewing.
You can send the view you are checking the -(int)retainCount message and check if it is one (ie the single retain from adding it to the array)? This question raises a red flag that you are doing soemthing that might be considered bad design, why are you doing this?
When you add anything to your NSMutableArray via 'addObject', that NSMutableArray does a retain on it. You will need to remove that object from the NSMutableArray to have it released, if that is what you are after.
[yourNSMutableArray removeObjectIdenticalTo:yourNSView];
Maybe try if([myView retainCount] == 1), then it is only retained in the windowManager.
[EDIT] Read about retainCount in NSObject reference. As JeremyP suggests, it is not smart to use this in your code, but think better of your code design.
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/retainCount

Do I have to release a NSLocalizedString?

The question is simple. Do I need to release a NSLocalizedString? For instance:
NSString *internetMessageTitle = NSLocalizedString(
#"You are currently not connected to a internet network"
#"Title of the message that tells the user there is no internet network");
Because I did this:
NSLog(#"Retain count of InternetMessageTitle is: %d",
[internetMessage retainCount]);
But it prints a retain count of 2. However I have read that the retainCount attribute is not very reliable. Should I release it twice?
And yes I have read the memory management rules and guide of the documentation but I don't see here any indication of NARC (NewAllocRetainCopy). I am still a beginner so I don't really know how NSLocalizedString makes strings.
Thank you!
EDIT1: I use this variable in a UIAlertView I don't know if the retainCount is increased there when I use it. And even when the alert is not used (inside an if, and if the if is skipped it isn't used) the retainCount is still 2 according to NSLog.
No, you must not release it. If you check how NSLocalizedString is defined you'll see:
#define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil]
That its normally a call to NSBundle's method that returns autoreleased string
I use this variable in a UIAlertView
I don't know if the retainCount is
increased there when I use it. And
even when the alert is not used
(inside an if, and if the if is
skipped it isn't used) the retainCount
is still 2 according to NSLog.
Yes, labels in UIAlert retain their content strings, but you should not worry about that - they will release them when get destroyed.
As you say, there's no NARC -- so you already know the answer is no.
And what you've read about retain counts? Heed it. Never look at the retain count as useful info. Never look at it all.
And FFS don't do something insane like calling release on an object several times just because you think it has a retain count > 1. That stuff is absolutely guaranteed to mess you up.
The Cocoa memory management rules are very simple. There's only one of consequence: all alloc/new*/*copy* calls must be balanced by a call to auto-/release. You're not calling a method or function named "alloc", starting with "new" or containing "copy", thus you shouldn't release.
Even simpler than following the memory rules is to use properties (object or class) when possible.

objective c - Release a singleton property

I have a singleton class that has an mutableDictionary. I initialise the dictionary in my root viewController. later on I would like to empty the dictionary and release the memory. Even though the retain count is 1 the release causes a crash:
-[CFDictionary release]: message sent to deallocated instance
is it possible to release a singleton property?
Thanks
First I'll reiterate what has been said a ton of times on here: Don't call -retainCount!! It is an implementation detail.
See: StackOverflow | when to use retainCount for an excellent recount of why you don't use retainCount.
Beyond that, I'd recommend looking into more information about some of the invariants to shoot for in writing singletons. Dave DeLong has a great recap of how (and more importantly why he does singletons) a certain way. The article includes links to other developers and their outlooks. I'd recommend familiarizing yourself with those tenets and then re-evaluating you implementation.
Finally, just to say it one more time:
Please everyone go to http://bugreport.apple.com and request that -retainCount be deprecated. The more people that ask for it, the better.
You should not be releasing other objects' properties. Allow the singleton to manage the dictionary itself and your design will be simpler.
As for the problem where Cocoa says you're overreleasing even though "the retain count is 1", there is only one good piece of advice you'll ever get about retain counts:
Don't look at them!
They are deceptive and an object's actual memory management is affected by all sorts of forces that the retain count cannot tell you about.
In this case, you're checking the retain count to see if the object still exists. But there is no such thing as an object with a retain count of 0 — when you release an object with a retain count of 1, it's deallocated. Any result you get back from a deallocated object is garbage, so you'll never be able to ask an object for its retain count and get back 0 — objects with a retain count of 0 literally do not exist.
Any object that is allocated can be released later. Sounds like you're over-releasing. Check your properties and all references to the object to make sure you're not over-releasing it. If the dictionary is inside the singleton class, the singleton class should be in charge of releasing it, not the customer viewcontroller.
Agree with the comments re retainCount. Just don't do it.
Initialize the dictionary in the singleton
Add/remove objects from the dictionary as needed in other classes
The overhead of an empty dictionary is trivial, I wouldn't worry about releasing it when empty
Use [dictionary removeAllObjects] to remove everything when needed
If the dictionary is storing objects you want to release in the event of a memory warning, have the singleton observe UIApplicationDidReceiveMemoryWarningNotification and have it remove all it's objects there.
If you really want your implementation to release the entire dictionary I would override the synthesized getter and add singleton methods to interact with the dictionary as follows:
in MySingleton.m:
- (NSMutableDictionary *)myDictionary
{
if (!_myDictionary) {
_myDictionary = [[NSMutableDictionary alloc] init];
}
return _myDictionary;
}
- (void)setObject:(id)object inMyDictionaryForKey:(NSString *)key
{
[self.myDictionary setObject:object forKey:key];
}
- (void)removeObjectInMyDictionaryForKey:(NSString *)key
{
[self.myDictionary removeObjectForKey:key];
if ([self.myDictionary count] == 0) {
self.myDictionary = nil;
}
}
- (void)removeAllObjectsFromMyDictionary
{
self.myDictionary = nil;
}

Memory Management on the iPhone

I'm sorry to ask such a simple question, but it's a specific question I've not been able to find an answer for.
I'm not a native objective-c programmer, so I apologise if I use any C# terms!
If I define an object in test.h
#interface test : something {
NSString *_testString;
}
Then initialise it in test.m
-(id)init {
_testString = [[NSString alloc] initWithString:#"hello"];
}
Then I understand that I would release it in dealloc, as every init should have a release
-(void)dealloc {
[_testString release];
}
However, what I need clarification on is what happens if in init, I use one of the shortcut methods for object creation, do I still release it in dealloc? Doesn't this break the "one release for one init" rule? e.g.
-(id)init {
_testString = [NSString stringWithString:#"hello"];
}
There is a neat acronym to remember what you have to release
N.A.R.C - new, alloc, retain, copy.
If it's not created with alloc, new, copy, mutableCopy then you're not responsible for releasing it.
This site has some good quick overviews of things like memory management.
Here's a quote from cocoadevcentral:
If you create an object using the
manual alloc style, you need to
release the object later. You should
not manually release an autoreleased
object because your application will
crash if you do.
Just to clarify things a bit. When you get an object through N.A.R.C. as sylvanaar says you do need to release it. In other cases you are getting an autoreleased object that will be released automatically at some later time. That will be bad in the code you presented here, because you do want this string to stay around at least as long as your object. So you actually need to do an explicit retain to keep it alive for your object.
That is not directly answering your question, but rather anticipating the next one ;-)
If you set an attribute with an autorelease, the object in the attribute can die at anytime beyond the immediate scope. Convenience methods i.e. ones that start with a type: string, array, dictionary etc, return autoreleased objects. You only use autoreleased objects when you don't care whether or not they survive beyond the present scope.
What you really need to do in this case is use accessors, either the synthesized or custom, to manage your retention automatically.
If you do:
#property(nonatomic, retain) NSString *_testString; // .h
#synthesize _testString; //.m
then in code use the reference form:
self._testString = [NSString stringWithString:#"hello"];
... then the only place you have to release _testString is in dealloc. The compiler will create synthesized accessors which will automatically manage the properties memory for you.
By the way, you should not use underscores for names. Apple reserves underscore names for itself so you can get a naming collision.
In the first part of the example you do indeed have to have a release for the string somewhere.
In the second part of the example because its an autoreleased you don't need to call the additional release in the dealloc method. This will actually cause a crash as you are attempting to send a message to something that no longer exists...
On the contrary, you need to retain the object you get from stringWithString:. As you correctly noted, you don't own that object and thus don't need to release it. But because you don't own it, it's free to disappear at any time, leaving you with a crash if you're lucky (and a very odd bug if you're not). So you need to retain the object, and then you do need to release it in dealloc.
All of this is explained very well in the memory management guide. I suggest you read it over a couple of times. It's not very long or difficult, and once you internalize it, you'll never have to wonder again.
The rule is if you create an object with new, alloc, copy or you retain it, you need to release it. Objects created in any other way must not be released.
So in your specific case, you would not need to release your string created with stringWithString.
By the way, I would recommend the Cocoa and Objective-C: Up and Running book for learning more about things like this. Great introduction if you are new to Cocoa programming.

Why should a self-implemented getter retain and autorelease the returned object?

Example:
- (NSString*) title {
return [[title retain] autorelease];
}
The setter actually retained it already, right? and actually nobody should bypass the Setter... so I wonder why the getter not just returns the object? It's actually retained already. Or would this just be needed in case that in the mean time another objects gets passed to the setter?
From here http://www.macosxguru.net/article.php?story=20030713184140267
- (id)getMyInstance
{
return myInstanceVar ;
}
or
- (id)getMyInstance
{
return [[myInstanceVar retain] autorelease] ;
}
What's the difference ?
The second one allows the caller to get an instance variable of a container object, dispose of the container and continue to play with the instance variable until the next release of the current autoreleased pool, without being hurt by the release of the instance variable indirectly generated by the release of its container:
aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);
If the "get" is implemented in the first form, you should write:
aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];
The first form is a little bit more efficent in term of code execution speed.
However, if you are writing frameworks to be used by others, maybe the second version should be recommanded: it makes life a little bit easier to people using your framework: they don't have to think too much about what they are doing…;)
If you choose the first style version, state it clearly in your documentation… Whatever way you will be choosing, remember that changing from version 1 to version 2 is save for client code, when going back from version 2 to version 1 will break existing client code…
It's not just for cases where someone releases the container, since in that case it's more obvious that they should retain the object themselves. Consider this code:
NSString* newValue = #"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue
This looks reasonable, but if neither the setter nor the getter uses autorelease the "Go on to do something" part will likely crash, because oldValue has now been deallocated (assuming nobody else had retained it). You usually want to use Technique 1 or Technique 2 from Apple's accessor method examples so code like the above will work as most people will expect.
Compare this code
return [[title retain] release]; // releases immediately
with this
return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier)
The second one guarantees that a client will have a non-dealloced object to work with.
This can be useful in a situation like this (client code):
NSString *thing = [obj title];
[obj setTitle:nil]; // here you could hit retainCount 0!
NSLog(#"Length %d", [thing length]); // here thing might be dealloced already!
The retain (and use of autorelease instead of release) in your title method prevents this code from blowing up. The autoreleased object will not have its release method called until AFTER the current call stack is done executing (end of the current run loop). This gives all client code in the call stack a chance to use this object without worrying about it getting dealloc'ed.
The Important Thing To Remember: This ain't Java, Ruby or PHP. Just because you have a reference to an object in yer [sic] variable does NOT ensure that you won't get it dealloc'ed from under you. You have to retain it, but then you'd have to remember to release it. Autorelease lets you avoid this. You should always use autorelease unless you're dealing with properties or loops with many iterations (and probably not even then unless a problem occurs).
I haven't seen this pattern before, but it seems fairly pointless to me. I guess the intent is to keep the returned value safe if the client code calls "release" on the parent object. It doesn't really hurt anything, but I doubt that situation comes up all that often in well-designed libraries.
Ah, ok. from the documentation smorgan linked to, it seems this is now one of the methods that Apple is currently recommending that people use. I think I still prefer the old-school version:
- (NSString *) value
{
return myValue;
}
- (void) setValue: (NSString *) newValue
{
if (newValue != myValue)
{
[myValue autorelease]; // actually, I nearly always use 'release' here
myValue = [newValue retain];
}
}