UIViewController初始化和加载顺序

我对Mac和iPhone上的UI编程相当陌生,而且碰到了让我感到困惑的东西。

一个UIViewController有3个涉及它的初始化和它的视图的方法:

  1. init(和类似init的方法)
  2. 的loadView
  3. viewDidLoad(委托方法)

我希望这些发生在上面的顺序。 首先UIViewController由其他对象分配,然后立即调用init(或其他一些init方法,如initWithStyle)。

只有对象被初始化后,我希望它调用自己的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]之后设置委托, loadView和viewDidLoad运行之后调用该方法(如上所示):

 UIViewControllerSubClass *someViewController = [[UIViewControllerSubclass alloc] init]; [viewController setDelegate:self]; 

如果我想以某种方式运行设置ViewController的代码,那么通知委托,代码应该驻留在init方法中? 是不是loadView的原因允许这样的代码在适当的时候运行?

它看起来像我将不得不创build一个新的initWithDelegate方法, 调用[超级初始化] 之前设置委托伊娃尔,这是正确的,还是我这样做是错误的?

提前致谢 :)

iPhone上的视图加载系统的工作原理是这样的:

初始化视图控制器(使用-init或-initWithNibName:bundle :)时,它实际上并不创build和初始化视图。 当你第一次调用-view时,它会调用-loadView。 默认情况下,-loadView只是从xib文件(nibName)加载视图。 但是,如果您覆盖此视图,则需要负责创build视图并将其分配给视图控制器的视图属性。 举个例子:

 - (void)loadView { UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]]; // add subviews self.view = view; [view release]; } 

每次创build视图时, 视图都会变得可见并显示在屏幕上 ,它会调用-viewDidLoad。 (-viewDidAppear / -viewDidDisappear是为了在屏幕上查看视图)

由于我们已经偏离了轨道,我们考虑内存pipe理。 当视图不在屏幕上时,系统会自动将视图控制器的视图属性设置为零。 问题是这个视图的所有子视图都在泄漏。 怎么会这样? 那么,每个子视图的保留计数是2(视图保留子视图,您的视图控制器有一个出口/伊维尔)。 当视图为零时,该视图的保留计数为1.如果视图没有显示,视图就没有任何意义了,所以在-viewDidUnload(这是一个钩子每当视图设置为零)。

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 { } 

只有在你使用故事板来存储在故事板中绘制的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创build的,那么只有initWithCoder会被调用。 在这种情况下loadView不会被调用。

正因为如此,似乎我所看到的大部分代码在像viewDidLoad这样的东西中进行了大部分的初始化操作,即使这看起来是错误的,但似乎是在两种情况下被调用的最好的方法,编程。

但是,这看起来不顺序的原因是[超级初始化]调用loadView等 –

拿@Nimrod的build议我做了这样的事情:

 -(void)viewDidLoad { // Init code here } 

我不知道这是否会导致内存泄漏问题,但看看苹果的文档,似乎并没有创造任何循环:

查看生命周期http://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/Art/loading_a_view_into_memory.jpg

这取自: http : //developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW1