I create a couple of UIButtons (with selectors) in a method (throughout the life cycle of the app) and stick them all into an NSMutableArray. The created buttons are NOT properties but the array is.
If I delete a button from the array, does the button automatically get released from memory?
If the answer to the above is no, what do I have to do to get it released from memory?
The button will indeed, eventually, be released from memory as no one is retaining it. Its retain count will be decremented regardless, but only if no one else is retaining it, it will be released from memory.
This is however a somewhat confusing mechanism - keep in mind that the UIButtons are views and are probably a part of your view hierarchy which also retains them. If they're also visible, they must be removed from their superview in order to be released.
Anything you put in a NSArray (and a NSMutableArray) gets retained by the array, and released when removed from the array or when the array itself is released. It's true for buttons and any other object.
Related
I guess i might not understand how memory deallocates in Swift properly and thats why i wanted to ask this:
If i create a Message to the user using a UIView with a Label. i show it with an animation and then use ".removeFromSuperview()". when does it's memory deallocates? what are the conditions for it to deallocate?
Im asking because if it doesn't deallocate until the app closes - it means that for the run of the app - each message shown and then hidden will take up memory for no good reason.
Thanks for anyone who explains :)
Views maintain a strong reference to their subviews. Once the subview is removed, the superview relinquishes this reference. If you have no other strong references the retain count will decrement to zero and the view will be released.
So I do understand, that I should release the objects that I own. (alloc/copy/retain stuff)
And I also do understand(kinda?), that if I had #property with retain in some of my class, or some instance variable with alloc/init, then I should write a custom dealloc to make sure those ones gets deallocated with that class.
What I do not understand is should I manually release the cell objects for example? (since I am creating it in cellForRowAtIndexPath with alloc/init? Yea, I know, that tableView should kill those cells when it gets deallocated, but do I want to make sure?
Also, could I manually release UILabel, UITextField and so on? I do know that those are gets killed when you deallocate the view, but again, still, do I want to make sure?
UPDATE:
Yea, thanks for the tip about reference counting, but the project exact purpose is to do some simple stuff, using manual memory management.
It is funny how most of the tutors nowadays skips this part entirely so the novice like myself have to figure all that stuff by themselves.
Objective C supports Automatic Reference Counting which does almost all memory management for you. I suggest you migrate your old code to ARC; this is quite easy (Xcode has refactoring support for this) and it will save you a lot of hassle.
Unless you have a strong/retain pointer to a UI element they will be automatically dealloced once they go out of the screen.
Regarding the cells - you should never dealloc them because they're intended to be reused. If you dealloc and re-init them you'll get a REALLY bad performance while scrolling.
Also, as Glorfindel said, consider using ARC (if you're not using already) and your life will be much easier.
I have always wondered what are the best practices while working with UIImageView objects and a will give you a few examples about what I'm unsure.
First of all I am working on a turn based game that supports multiple matches at the same time, and certain views (a background image, label and a few buttons) will be loaded to self.view very often. What is the best way to display them, add them and then remove:
[self.view addSubview:view];
[view removeFromSuperView];
Or is the best way to add them and play with the hidden property (show and hide whenever i need, even in different matches)?
Another question is do I need to set an UIImageView to nil after I remove it from superview?
And the last question is: If I have a UIView class that I load to an UIImageViewController and want to release/remove it from within [self removeFromSuperView] is enough to release all the memory occupied by that view class?
If those views are loaded often into the screen, the best approach is to hide them instead of removing them. I'll remove them when I'm not using them anymore.
Removing a view from the superview reduces the retain count of the object in 1. If you are using ARC, you shouldn't worry about it, if you are not, be sure that the retain count is 0 after removing it (+1 for every alloc, add to subview, and -1 for every release, autorelease, removeFromSuperView). If after removing the view the retain count still 1, you can do = nil to release it. If the retain count of an object is 0, then the system will free it.
Same as 2.
Regarding points 2 and 3, it really depends on the scope of your UIImageView. If you declared it as a strong property, then you will have to set it to nil in order for ARC to release the memory. If it just a variable inside a method, then at the end of the execution of the method body, the variable will be released anyway (and be retained only by the view hierarchy).
I have read several Q&A and documentations which state that we should use weak for IBOutlet unless it's top level objects from File's Owner.
But if I still use strong/retained, is there any major downside, or is it just redundant because the subview is already retained with addSubview:?
Note: please do not copy definition of weak / strong here, I don't need that, I want to see real world cases where using strong for IBOutlet could cause problems. Thanks.
With MRC, if you use retain, you will have to release the memory by yourself.
With ARC, if you use strong and the system requests memory from your app (= your view will be unloaded), you will have to release the memory by yourself (note that the controller would be still be active, so no dealloc called there)
For most outlets, weak/assign is appropiate because you don't need to care about releasing the memory.
Exceptions:
IBOutletCollection must be strong/retain. The collection (NSArray) is not retained by the view hierarchy.
You add/remove views dynamically. If you want to remove a view from your view hierarchy and use it again later, the view must be retained somewhere, otherwise it gets deallocated at the time of removal. However, note that you can always retain it in code at the time of removal.
I will mark this as "accepted" until someone provides a better answer.
Apparently the only downside is that when your view receives a memory warning, it would unload the view, and optimally all the subviews should be released. But since your controller still retains them if you use strong, you will have to nil them out manually in viewDidUnload.
From iOS 6, view is not unloaded upon receiving memory warning, so this becomes inconsequential. From a practical point of view there is no major difference between using weak or strong for IBOutlet afaik, unless you have to unload your view manually in your application.
I'm trying to conform to Apple's guidelines about responding to low memory warnings in my app. The guidelines say: "Upon receiving (a low memory warning), your application must free up as much memory as possible by releasing objects that it does not need or clearing out memory caches that it can recreate later."
The question is, how to 'free up' memory, using ARC?
For example, suppose I have an image in the view hierarchy of a view that is not on screen. In didReceiveMemoryWarning, I currently remove it from the view by calling removeFromSuperview, but I still have a pointer to the UIImage itself. Should I also try to free up this memory? How? By assigning nil to the pointer?
TIA: John
By the time you get -didReceiveMemoryWarning, your view should have been released automatically by system and -viewDidUnload should be called. So if you don't hold references to subviews of the view you are not responsible to free them.
Otherwise, if you do hold references to some resources you want to free up, you just nullify your references by assigning "nil" to them for NSObjects, and call corresponding release functions for other types of references, e.g, CFRelease for Core Foundation objects.
Make all IBOutlet properties with the strong attribute.
Set all IBOutlet properties all to nil in viewDidUnload.