Memory management help for Objective-C - objective-c

I'm studying memory managment in UIviewController, i'm a little confused, the important points to remember are:
viewDidLoad is called every time the view is shown, here I alloc variables of any kind.
viewDidUnload is called in case of low memory, I set all the property to nil.
dealloc, I release all property.
Is it all right?
Also, if I don't link a label to a IBOutlet, have I a memory leak or the system dealloc it anyway?

No. -viewDidLoad is called when the controller loads its view, not every time the view is displayed. Perhaps you're thinking of -viewWillAppear. Otherwise, your points are about right.
If you don't connect something to an outlet, the outlet will simply remain nil -- there's no leak. The label will generally be retained by its enclosing view, and will be released when the rest of the view hierarchy is released.

Related

Remove Object From SuperView but Memory still allocated? (ARC)

I'm having some issues with my application's memory management. I allocate an NSView class and put it on one of my Windows. After some time, I remove the object from the superview and then put another object in it's place. The problem that I'm having is that the memory isn't freed when I remove it. It continues to hold as much memory as it previously held, and if I add more of that class, it continues to pile onto the memory. My question is, will removing that object get rid of all objects that the class held, or are some pointers being held onto, even after the object is removed? I can post code if necessary.
Thanks!
Edit:
Here's the code that I use to allocate it
MyClass *theClass1 = [[MyClass alloc] initWithFrame:frameRect];
[self.window.contentView addSubview:theClass1];
Here's the code that I use to deallocate it
[[self.window.contentView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
I create it on a timer, updated every minute. I do not reference it anywhere else.
The memory for each object should be treated separately for each instance of a class. Removing one instance should not affect the allocation of other instances (unless you had some custom code looking for other instances of the class).
As for the NSView removal, removeFromSuperview does release the receiver (the view being removed), which is why the Apple docs on NSView say to retain it if it is still needed later.
Posting the code where it is declared, instantiated, added, then removed would be helpful for a more specific answer.

When removing dynamically created objects in Objective-C, what should I set to nil?

Easy question alert, but I want to be sure I'm not being stupid.
In my iPad app I'm dynamically creating a UIView, and filling it with UIButtons, UIImageViews, sometimes a MPMoviePlayerController, sometimes a UIImageView with a few UIImages as an animation.
After a certain amount of time, I'm removing the view from the screen and discarding it.
The question is: should I be setting any of these objects to nil?
I'm releasing everything after I allocate it, and I'm not getting any leaks. BUT my app is eventually crashing after running out of memory. Each one of these views I build seems to be lurking somewhere in memory.
Any help, much appreciated.
Duncs
It's hard to comment without code or knowing if you are using ARC or not (guessing not, because you said "releasing").
Do an Analyze and fix every problem it flags. It's very good at telling you if you are retain/releasing correctly
Use the Leaks Instrument to find leaks
If you have no more leaks, but are still crashing, then turn on Zombies and make sure you aren't releasing anything too early
Setting a variable to nil doesn't do anything to release the memory. If you have a #property that is declared with (retain), the auto-generated setter will make it so setting the property to nil will release the old value.
The dealloc of any class that has properties needs to do this to all properties that are pointers to retained objects. For UIViewControllers, you would also want to do this in viewDidUnload for IBOutlet properties.
When you are using ARC, while you add the UIView as subview of another UIView, the retain count will increase. On you "removeFromSuperview" it, it will decrease and it will be deallocated. In a Non-Arc environment, after allocating it and adding it to a UIView the retain will be of 2, but then you release it, so it will go back to 1. So there is always a balance between those. To check what's going on, you should use Instruments, to pinpoint the problem.
It only makes sense to "nil" it is when you have a #property of the iVar (for retain). Why is that? Because it will release the old value and it will set the new one to the value passed (in this case nil). You probably think that the issue is related the UIViews but might be something else. That's why I advise you to use Instruments.

Interface Builder sets control outlets to nil -- why?

Using xcode 4.2 for iPhone app, without ARC ---
When I create an outlet using the interface builder xcode adds two lines of code to my viewController. One in viewDidUnload: -- [self setMyOutlet:nil] and second in dealloc -- [myOutlet release].
I understand the latter (the release). But why set the outlet to nil in viewDidUnload. Doesn't viewDidUnload get called before dealloc and won't setting the outlet to nil negate the release operation in dealloc? Setting to nil makes sense I would think for building a Mac application which is using garbage collection -- but it doesn't make sense for an iPhone app.
Why does the interface builder do this? Should I delete the lines which set the outlets to nil?
viewDidUnload may be called and may be not called. It depends on the current memory usage. dealloc is a place where you should clean all your properties (like arrays, custom objects). In viewDidUnload you clean views and perhaps objects created to support the view. viewDidUnload mean that your view is unloaded (but not whole view controller) and it may be created and loaded again (in viewDidLoad, of course) in the future.
Why to nil - Objective-C Difference between setting nil and
releasing
Understanding How Views Are Loaded and
Unloaded
viewDidUnload is not called everytime before a dealloc, see what the apple docs say..
When a low-memory condition occurs and the current view controller’s
views are not needed, the system may opt to remove those views from
memory. This method is called after the view controller’s view has
been released and is your chance to perform any final cleanup. If your
view controller stores separate references to the view or its
subviews, you should use this method to release those references. You
can also use this method to remove references to any objects that you
created to support the view but that are no longer needed now that the
view is gone. You should not use this method to release user data or
any other information that cannot be easily recreated.
so the idea behind it is too release any unwanted objects which can be created easily.
Now coming to the part where it sets the properties to nil.. it does so because this way you release all the memory and set the objects to nil (thus bringing your down your memory usage) and after this if a dealloc is called your app will not crash as in objective-c you can send release messages to nil objects..
I would advise you to read the apple ViewController Programming Guide , it will clear a lot of your questions.... hoping this clears some of the air.. :D

Keeping pointers to subviews

Subviews added to a view are automatically retained by the view. Suppose you want to have a separate pointer to the same subview so you don't need to constantly retrieve it via its tag.
What type of #property is necessary for such a case? I assume that setting the property to retain is not a good idea since the main view is already retaining it? Should it be assign?
Or, is using #property entirely unnecessary here unless you plan to re-assign it later or refer to it with dot notation?
You can use either retain or assign.
Of course, if you use retain, you have to set the property to nil or release its object in viewDidUnload and dealloc.
The reason some people prefer retain is because it means the property is still valid in viewDidUnload. So if you have other cleanup to do, and that cleanup requires the view to still exist, you can do it in viewDidUnload.
If you use assign, you don't have to set the property to nil in viewDidUnload and dealloc (though it would be good practice). However, by the time you receive viewDidUnload, the view has already been released, so you can't use it at that point for other cleanup. Instead you have to override didReceiveMemoryWarning to do the cleanup before calling [super didReceiveMemoryWarning].
In iOS 5.0, you can do the cleanup in viewWillUnload instead of overriding didReceiveMemoryWarning.
Consider these two things:
There's no problem with retaining an object several times provided that each retain is balanced with release. With respect to properties, this just means that you should set your property to nil when you're done with it.
The basic idea behind memory management in Objective-C is that you worry about retaining the objects that you're using and let other objects worry about the objects that they're using.
Considering these, I'd advocate using retain. If you rely on he fact that a view retains its subviews, you've suddenly made your code dependant on external behavior. I'm not saying that UIView is likely to stop retaining its subviews, but if you keep a non-retained reference to a subview and later remove that subview from its superview you're code is likely to crash.
Some folks do use assign for outlets pointing to subviews when they know those subviews will never be removed. Personally, I don't see the point of relying on another object to retain something for you when retaining that thing yourself is so simple and cheap.

Memory management in interface builder

If I put a label in Interface Builder, and don't connect it with an IBOutlet, do I have a memory leak? Or does the system call dealloc itself?
No, you won't have a leak. Without an IBOutlet, you are never directly calling retain on the object. Therefore the only thing that will be retaining the object is the view that the label is a subview of, because when you add a subview to a view, it calls retain. When the parent view is dealloced, it will call release on all of its subviews, which will dealloc the label.