更新:
澄清问题的背景;问题不在于如何避免该问题,而是要澄清该文档的含义,因为我的实验表明我期望根据文档卸载的视图并未卸载。我想了解这是否是一个错误,或者我是否误解了文档。为了解决这个问题,我知道在 viewWillAppear 而不是 viewDidLoad 中设置图像,并在 viewDidDisappear 中将图像设置为 nil,正在释放内存并且应用程序不会崩溃。但是,我想了解是否应该使用初始代码释放内存,因为实验是模拟将此类视图控制器用作插座,并在 Interface Builder 中设置 UI 图像(背景...),而不是设置它们在 viewWillAppear 中的代码中......
原文:
我正在尝试了解 iOS6 的一些新方面,如 View Controller Programming Guide 中所述:
在 iOS 6 及更高版本中,视图控制器在需要时卸载自己的视图视图控制器的默认行为是在第一次访问视图属性时加载其视图层次结构,然后将其保存在内存中,直到视图控制器被释放。视图在屏幕上绘制自身所使用的内存可能非常大。但是,当视图未附加到窗口时,系统会自动释放这些昂贵的资源。大多数视图使用的剩余内存足够小,以至于系统不值得自动清除和重新创建视图层次结构。
假设我正在创建一个带有 rootViewController 的简单应用程序。这个 rootViewController 有几个子视图控制器,都声明为 IBOutlets,而不是在代码中分配。
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController1;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController2;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController3;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController4;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController6;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController7;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController8;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController9;
@property(nonatomic,strong) IBOutlet ChildViewController *childViewController10;
rootViewController 有几个按钮,按下每个按钮都会对每个 childViewController 执行简单的 presentModalViewController 操作
-(IBAction)showChild1Action:(id)sender{
[self presentModalViewController:self.childViewController1 animated:true];
}
每个 childViewController 都有一个关闭按钮,用于关闭子视图控制器。
-(IBAction)closeAction:(id)sender{
[self dismissModalViewControllerAnimated:true];
}
My expectation from the documentation was that the child view controller view objects would be released from memory, as the child view controllers are dismissed.
However I purposely tested with large view objects, and running profile on such an app, the memory usage just keeps growing as each child controller gets presented, and the app eventually crashes after I present child controller #7 or so.
What is your understanding of what has changed in iOS6 in that aspect?
RootViewController.h
#import <UIKit/UIKit.h>
#import "ChildViewController.h"
@interface RootViewController : UIViewController
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController1;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController2;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController3;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController4;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController5;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController6;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController7;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController8;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController9;
@property(nonatomic,strong) IBOutlet ChildViewController *level2ViewController10;
-(IBAction)showChild1Action:(id)sender;
-(IBAction)showChild2Action:(id)sender;
-(IBAction)showChild3Action:(id)sender;
-(IBAction)showChild4Action:(id)sender;
-(IBAction)showChild5Action:(id)sender;
-(IBAction)showChild6Action:(id)sender;
-(IBAction)showChild7Action:(id)sender;
-(IBAction)showChild8Action:(id)sender;
-(IBAction)showChild9Action:(id)sender;
-(IBAction)showChild10Action:(id)sender;
@end
RootViewController.m
#import "RootViewController.h"
@interface RootViewController ()
@end
@implementation RootViewController
@synthesize level2ViewController1;
@synthesize level2ViewController2;
@synthesize level2ViewController3;
@synthesize level2ViewController4;
@synthesize level2ViewController5;
@synthesize level2ViewController6;
@synthesize level2ViewController7;
@synthesize level2ViewController8;
@synthesize level2ViewController9;
@synthesize level2ViewController10;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(IBAction)showChild1Action:(id)sender{
self.level2ViewController1.index=0;
[self presentModalViewController:self.level2ViewController1 animated:true];
}
-(IBAction)showChild2Action:(id)sender{
self.level2ViewController2.index=1;
[self presentModalViewController:self.level2ViewController2 animated:true];
}
-(IBAction)showChild3Action:(id)sender{
self.level2ViewController3.index=2;
[self presentModalViewController:self.level2ViewController3 animated:true];
}
-(IBAction)showChild4Action:(id)sender{
self.level2ViewController4.index=3;
[self presentModalViewController:self.level2ViewController4 animated:true];
}
-(IBAction)showChild5Action:(id)sender{
self.level2ViewController5.index=4;
[self presentModalViewController:self.level2ViewController5 animated:true];
}
-(IBAction)showChild6Action:(id)sender{
self.level2ViewController6.index=5;
[self presentModalViewController:self.level2ViewController6 animated:true];
}
-(IBAction)showChild7Action:(id)sender{
self.level2ViewController7.index=6;
[self presentModalViewController:self.level2ViewController7 animated:true];
}
-(IBAction)showChild8Action:(id)sender{
self.level2ViewController8.index=7;
[self presentModalViewController:self.level2ViewController8 animated:true];
}
-(IBAction)showChild9Action:(id)sender{
self.level2ViewController9.index=8;
[self presentModalViewController:self.level2ViewController9 animated:true];
}
-(IBAction)showChild10Action:(id)sender{
self.level2ViewController10.index=9;
[self presentModalViewController:self.level2ViewController10 animated:true];
}
@end
ChildViewController.h
#import <UIKit/UIKit.h>
@interface ChildViewController : UIViewController
@property(nonatomic,weak) IBOutlet UIImageView *image1;
@property NSInteger index;
-(IBAction)closeAction:(id)sender;
@end
ChildViewController.m
#import "ChildViewController.h"
@interface ChildViewController ()
@end
@implementation ChildViewController
@synthesize image1;
@synthesize index;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
if(self.index==0)
[self.image1 setImage:[UIImage imageNamed:@"IMG1.JPG"]];
if(self.index==1)
[self.image1 setImage:[UIImage imageNamed:@"IMG2.JPG"]];
if(self.index==2)
[self.image1 setImage:[UIImage imageNamed:@"IMG3.JPG"]];
if(self.index==3)
[self.image1 setImage:[UIImage imageNamed:@"IMG4.JPG"]];
if(self.index==4)
[self.image1 setImage:[UIImage imageNamed:@"IMG5.JPG"]];
if(self.index==5)
[self.image1 setImage:[UIImage imageNamed:@"IMG6.JPG"]];
if(self.index==6)
[self.image1 setImage:[UIImage imageNamed:@"IMG7.JPG"]];
if(self.index==7)
[self.image1 setImage:[UIImage imageNamed:@"IMG8.JPG"]];
if(self.index==8)
[self.image1 setImage:[UIImage imageNamed:@"IMG9.JPG"]];
if(self.index==9)
[self.image1 setImage:[UIImage imageNamed:@"IMG10.JPG"]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
-(IBAction)closeAction:(id)sender{
[self dismissModalViewControllerAnimated:true];
}
When using Instruments I get these observations:
The memory allocation instrument is showing what I would expect to see: total allocation that goes up when child view controller is presented, goes down when child view is dismissed
However the activity indicator is telling a different story, with real memory increasing with every presentModalViewController, and never decreasing when dismissing them