私はMacとiPhoneでのUIプログラミングにかなり慣れていないので、やや困惑する何かに出くわしました。
UIViewControllerには、その初期化とビューを含む3つのメソッドがあります。
これらが上記の順序で発生することを期待しています。最初にUIViewControllerが他のオブジェクトによって割り当てられ、次にinitがすぐに呼び出されます(またはinitWithStyleなどの他のinitメソッド)。
オブジェクトが初期化されると、独自のloadView関数が呼び出され、その後、ビューが読み込まれるとviewDidLoadデリゲートメソッドが呼び出されます。
たとえば、これは起こりません。
@implementation UIViewControllerSubclass
- (id)init {
NSLog(@"0");
if (self = [super init]) {
NSLog(@"1");
}
return self;
}
- (void)loadView {
[super loadView];
NSLog(@"2");
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"3");
}
@end
コンソール出力を生成します。
0
2
3
1
したがって、loadViewメソッドとviewDidLoadメソッドは、デリゲートを呼び出すことができません。デリゲートは通常[super init]の呼び出しの後に設定されるため(上記を参照)、afterloadViewとviewDidLoadが実行されました:
UIViewControllerSubClass *someViewController = [[UIViewControllerSubclass alloc] init];
[viewController setDelegate:self];
何らかの方法でViewControllerをセットアップするコードを実行して、デリゲートに通知する場合、コードはinitメソッドに存在する必要がありますか?そのようなコードを適切なタイミングで実行できるようにするために、loadViewが存在する理由はありませんか?
私は、デリゲートivarbeforeを設定する新しいinitWithDelegateメソッドを作成する必要があるように見えます[super init]を呼び出す、または私はこれについて間違った方法で行っていますか?
前もって感謝します :)
IPhoneのビュー読み込みシステムは次のように機能します。
View Controllerを初期化するとき(-initまたは-initWithNibName:bundle:を使用)、実際にビューを作成および初期化することはありません。初めて-viewを呼び出すと、-loadViewが呼び出されます。デフォルトでは、-loadViewはxibファイル(nibName)からビューをロードするだけです。ただし、これをオーバーライドする場合は、ビューを作成し、View ControllerのViewプロパティに割り当てる必要があります。例として:
- (void)loadView
{
UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
// add subviews
self.view = view;
[view release];
}
ビューを作成するたびに、表示されて画面に表示されるビューとは異なります、-viewDidLoadを呼び出します。 (-viewDidAppear/-viewDidDisappearは、画面上のビューの可視性のためです)
すでに軌道に乗っていないので、メモリ管理について考えてみましょう。ビューが画面外にある場合、システムは自動的にView ControllerのViewプロパティをnilに設定します。問題は、そのビューのすべてのサブビューがリークしていることです。どうして?さて、各サブビューの保持カウントは2です(ビューはサブビューを保持し、View Controllerにはアウトレット/ ivarがあります)。ビューがnilの場合、そのビューの保持カウントは1です。ビューが表示されていない場合、ビューが保持されても意味がないので、-viewDidUnload(これは、ビューがnilに設定されている場合)。
initWithNibName:bundle: メソッドは、UIViewControllerクラスの指定された初期化子です。
Initの代わりにオーバーライドして使用してみてください。
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
}
return self;
}
...
UIViewControllerSubClass *someViewController = [[UIViewControllerSubclass alloc] initWithNibName:@"UIViewControllerSubclass" bundle:nil];
-(void)awakeFromNib
{
}
は、ストーリーボードを使用して、ストーリーボードのNib --- meansインターフェイスバンドルに描画されたViewControllerを格納する場合にのみ呼び出されます。
適切なシーケンスは
-(void)initWithCoder
-(void)awakefromNib //(if story board is used)
or
-(void)loadView----() //if manually generating the view contoller
-(void)viewDidLoad-----(called only once in the life cycle of viewController)
-(void)viewWillAppear
-(void)viewDidAppear
新しいViewControllerに移動中
-(void)viewWillDisappear
-(void)viewDidDisappear
最初のViewControllerに戻る間
-(void)viewWillAppear
-(void)viewDidAppear
gerry3が正しい。このことも私を混乱させます。 指定イニシャライザ のドキュメントをご覧ください。
また、ロードされるnibによってコントローラーが作成された場合、initWithCoderのみが呼び出されることに注意してください。その場合、loadViewも呼び出されません。
このため、私が見たコードのほとんどは、それが間違っているように見えてもviewDidLoadのようなものでほとんどの初期化を行っているように見えますが、何かがペン先にロードされて作成される両方のケースで呼び出される最良の方法のようですプログラムで。
しかし、これが順不同に思える理由は、[super init]がloadViewなどを呼び出しているためです。
@Nimrodの提案を受けて、私は次のようなことをしました:
-(void)viewDidLoad
{
// Init code here
}
これがメモリリークの問題を引き起こす可能性があるかどうかはわかりませんが、Appleのドキュメントを見ると、サイクルを作成していないようです。