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).
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.
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.
I have a small question when programming objects in objective-C. I have an App that is just about complete and everything works fine. My question is that I set my objects to nil and release them at appropriate times.
But is this enough or when and where should I use removefromsuperview?
In the case of adding a UIButton to a UITableViewCell I add the UIButton with the following code:
UIButton *buttonReset = [UIButton buttonWithType:UIButtonTypeContactAdd];
buttonReset.frame = CGRectMake(250.0f, 7.0f, 75.0f, 30.0f);
[cell addSubview:buttonReset];
buttonReset addTarget:self action:#selector(resetSettings) forControlEvents:UIControlEventTouchUpInside];
buttonReset = nil;
[buttonReset release];
Do I also need to use
[buttonReset removeFromSuperview];
in this case?
buttonReset = nil;
[buttonReset release];
This doesn't make sense. You set a pointer to nil (null pointer) and then send a message to it. In most other languages this would result in a crash. In Objective-C it's allowed, but nothing will happen. You have to release before setting to nil. But you shouldn't do neither in this case, because buttonReset is an autoreleased object (you didn't use alloc/init to create it), so you don't own it and therefore you must not release it.
You also don't have to use removeFromSuperview in this case. You add a button (a subview) to your cell (the superview). The superview will hold a strong (retaining) reference of the button. When the cell is then released, it will also handle all of its subviews. You only have to remove it yourself when you actually want to do that, but not for memory management reasons.
If you didn't already know about it, you might want to consider using Automatic Reference Counting (ARC) in the future.
No, you should not call [buttonReset removeFromSuperview];, at least not right away: if you do, the button would disappear from screen (given the name of the method, this should come as no surprise). Moreover, you do not need to set your button to nil.
Calling removeFromSuperview is needed when you need the control to be dropped from the screen. If you also release it, the object representing your control would be destroyed. For example, if you added a button programmatically for a specific task, and have to remove that button once the task has been accomplished, calling removeFromSuperview is appropriate.
Calling removeFromSuperview on a view causes it to be removed from its superview. This will make the targetted view disappear from the screen with all the view it contains.
In your situation, I would just set the object to nil and be done with it.
See does removefromsuperview releases the objects of scrollview?.
There are interesting informations in it.
but it's worth digging deeper into this, because it's a very important
concept in ObjC. You should never call -release on an object you
didn't -retain explicitly or implicitly (by calling one of the Three
Magic Words). You don't call -release in order to deallocate an
object. You call it to release the hold you have put on the object.
Whether scrollview is retaining its subviews is not your business (it
does retain its subviews, but its still not your business). Whether
-removeFromSuperview calls -release is also not your business. That's betweeen the scrollview and its subviews. All that matters is that you
retain objects when you care about them and release them when you stop
caring about them, and let the rest of the system take care of
retaining and releasing what it cares about.
you should use just the
[buttonReset removeFromSuperview];
and then
buttonReset = nil;
as apple saying
If the receiver’s superview is not nil, the superview releases the receiver. If you plan to reuse a view, be sure to retain it before calling this method and release it again later as appropriate.
in UIView Referance
Fairly straightforward question in two parts.
If a view retains its subviews, and we create a view hierarchy in Interface Builder where views are nested within others, why does the IBOutlet property for the nested subviews need to be set to retain? Wouldn't assign be an acceptable parameter for those subview properties?
I have a UIView subclass which adds a few subviews to itself upon initialization. To capture references to specific subviews, #property (nonatomic, assign) will suffice for that need, correct? For example, the main UIView adds a player score subview, then later wants to talk to that player score to update it. That reference only needs to be assigned, as the view proper is automatically retain by the UIView class, right?
1) It doesn't need to be. assign is fine. What made you think that you have to use retain?
2) Yes
By the way, are you using ARC? If so, use weak instead of assign (please don't ask why, it is well explained in every corner of stack overflow and the Internet in general).
Yes, it is true that in your case the subview will be retained by the view, so we don't technically need to retain it again. However, that is kind of fragile. What if in the future you add some code that removes that subview from its superview? Then you have a dangling pointer unless you make sure to nil it out.
It is general convention to retain instance variables, unless it is necessary not to (e.g. for delegates). If we go down the path of saying "oh we don't need to retain this instance variable because it's retained here; oh we do need to retain this other one because it's not retained; etc.", then we end up with very haphazard memory management, where every time we add an instance variable, we have to go and think about whether it is retained by something else or not; and then every time we use it, we have to remember whether we decided to retain it or not. It is precisely the kind of memory management nightmare that the memory management rules are designed to avoid.
And retaining the instance variable, what harm does it do? In this case, it just causes an additional retain and release when we assign it. Not a big deal, for the benefit of simplicity and consistency.
I am creating a Custom Grid kind of View for my App. I am placing many subviews on them. I have a necessity to reload the Gird with new set of Views based on users' interaction and when new data arrives.
I allocate memory for my subviews as this:
while(index < count)
CustomGridTile *view = [[CustomGridTile alloc] initWithFrame:frame];
[self addSubView:view];
[view release];
}
When I wanted to refresh my Grid, I remove all subviews from their superViews and create new set of Grid Tiles (subviews), add to the Custom Gird View and release them.
Am I doing things correctly? Can this bring me memory related issues?
As long as you are removing the subview it should release memory.
Explanation:
When you allocate the view CustomGridTile its retain count becomes 1. When you add it as the sub view, its retain count would become 2. When you release, retain count becomes 1. Finally when you remove the subview, its retain count will become zero and should be released.
releasing the views can bring some issues - i suggest attempting an autorelease on them or something along those lines
otherwise what i would do is when you remove it from the superview release it as well, but releasing after you add it as a subview has given me troubles in the past