Let's say i'm working on an app with a large number of views and i have some problems understanding memory management when the UIViewController segues to another UIViewController.
Which of the following object should i release in viewDidDisappear: ?
@property (weak, nonatomic) IBOutlet UIImageView *background;
@property (strong,nonatomic) UILabel *playerLevel;
- (void)viewDidLoad
{
[super viewDidLoad];
map = [[MapView alloc]init];
[self.view addSubview:map];
}
Is this the correct way to do this ?
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:YES];
[_background removeFromSupeview];
[self.playerLevel removeFromSupeview];
[map removeFromSupeview];
_background = nil;
self.playerLevel = nil;
map = nil;
}
You don't need to do anything. ARC will implement the dealloc
method for you, which will call all releases for your retained properties.
I really recommend you read the memory management documentation from apple, it will help to understand what ARC is really doing, including understanding how retain cycles can be avoided.
You don't need to release anything. ARC will take care of it when deallocating your view controller.
viewDidDisappear
: only notifies the view controller that its view was removed from a view hierarchy. This is an optional method that your view can utilize to execute custom code when the view does indeed disappear. All views will be released automatically by ARC.
When you segue (presenting/pushing to a new scene), the previous view controller's views are generally not released. Only when a view controller is dismissed/popped (or you call an unwind segue) would it generally get deallocated. If you're seeing memory consumption continue to grow, make sure you are presenting/pushing to go forward, but dismiss/pop/unwind to return back to a previously presented view controller.
(A very long time ago, in low memory situations iOS would unload/release views that were not current visible, but Apple deprecated that in iOS 6.0 because it just didn't save much memory and caused too many problems for developers.)
Bottom line, because you're using ARC, you don't need this viewDidDisappear
method at all. When the view is deallocated, that eliminates any strong references it maintains on its subviews, resulting in them being deallocated automatically, too (assuming you didn't create other strong references elsewhere, which you shouldn't be doing, anyway). Likewise, when the view controller is deallocated, any strong
references it has are also resolved, resulting in those properties being released, too.
As an aside, a view controller maintains strong
reference to the top level view
, but it doesn't need to maintain strong
references to that view's subviews. When addSubview
is called, the top level view maintains its own strong references to its subviews. Thus the view controller owns the view, but the view owns its subviews.
This code sample suggest a bit of a logical inconsistency, where your IBOutlet
is weak
(as it should), but your label (and presumably the map
) are strong
. This isn't going to cause a problem, but suggests a logical inconsistency in the object ownership diagram.
I might suggest making the playerLevel
property (and map
, presumably) weak
references (just like the IBOutlet
). And, if instantiating these programmatically, you'd do something like:
@property (weak, nonatomic) UILabel *playerLevel;
- (void)viewDidLoad {
[super viewDidLoad];
UILabel *playerLevel = ...
[self.view addSubview:playerLevel];
self.playerLevel = playerLevel;
}
So, we create a local UILabel
variable, configure it, add it to the subview, and then set the weak
property to reference that label. The use of that local variable is important when dealing with weak
properties, so it doesn't get released before you have a chance to call addSubview
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.