アップデート:
質問の文脈を明確にするため。問題は問題を回避する方法ではなく、ドキュメントの一部が何を意味するかを明確にすることです。私の実験では、ドキュメントに基づいてアンロードする予定だったビューがアンロードされていないことが示唆されています。これがバグなのか、ドキュメントを誤解しているのかを理解したいと思います。代わりに問題を解決するために、viewDidLoad ではなく viewWillAppear で画像を設定し、viewDidDisappear で画像を nil に設定すると、メモリが解放され、アプリがクラッシュしないことがわかっています。ただし、初期コードでメモリを解放する必要があるかどうかを理解したいと思います。実験は、このようなビュー コントローラーをアウトレットとして使用し、UI 画像 (背景...) を設定する代わりに Interface Builder で設定することをシミュレートするためです。ビューのコードでそれらを表示します...
オリジナル:
View Controller Programming Guide に記載されているように、iOS6 のいくつかの新しい側面を理解しようとしています:
iOS 6 以降では、View Controller は必要に応じて独自のビューをアンロードする View Controller のデフォルトの動作は、View プロパティが最初にアクセスされたときにビュー階層をロードし、その後、View Controller が破棄されるまでメモリに保持することです。ビューが画面上に自分自身を描画するために使用するメモリは、潜在的に非常に大きくなります。ただし、ビューがウィンドウに関連付けられていない場合、システムはこれらの高価なリソースを自動的に解放します。ほとんどのビューで使用される残りのメモリは十分に小さいため、システムがビュー階層を自動的に消去して再作成する価値はありません。
rootViewController を使用して単純なアプリを作成しているとしましょう。この rootViewController にはいくつかの子 View Controller があり、コードで割り当てられるのではなく、すべて 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];
}
ドキュメントからの私の期待は、子View Controllerが閉じられると、子View Controllerビューオブジェクトがメモリから解放されることでした。
ただし、大きなビュー オブジェクトを使用して意図的にテストし、そのようなアプリでプロファイルを実行すると、子コントローラーが表示されるたびにメモリ使用量が増加し続け、子コントローラー #7 などを表示するとアプリが最終的にクラッシュします。
その点で iOS6 で何が変わったのか、あなたはどのように理解していますか?
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];
}
Instrumentsを使用すると、次のような観察結果が得られます。
メモリ割り当てインストゥルメントは、私が期待するものを示しています:子ビューコントローラーが表示されると増加し、子ビューが閉じられると減少する合計割り当て
ただし、アクティビティ インジケーターは別の話をしています。実際のメモリはすべての presentModalViewController で増加し、それらを破棄しても決して減少しません。