UIViewController初始化和加载顺序
我对Mac和iPhone上的UI编程相当陌生,而且碰到了让我感到困惑的东西。
一个UIViewController有3个涉及它的初始化和它的视图的方法:
- init(和类似init的方法)
- 的loadView
- 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/ViewLoadingandUnloading/ViewLoadingandUnloading.html#//apple_ref/doc/uid/TP40007457-CH10-SW1