UIViewController的顺序初始化和加载 [英] Order of UIViewController initialization and loading

查看:119
本文介绍了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

生成控制台输出: / p>

  0 
2
3
1
因此,loadView和viewDidLoad方法不能进行委托调用,因为委托通常在调用[super init]之后设置,其中(如图所示)上面)在 loadView和viewDidLoad运行后被调用

  UIViewControllerSubClass * someViewController = [[UIViewControllerSubclass alloc ] 在里面]; 
[viewController setDelegate:self];

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



它看起来像我一样,我必须创建一个新的initWithDelegate方法在调用[super init]之前设置代理ivar ,这是正确的,还是我错误的方式?



预览:)

解决方案

iPhone上的视图加载系统的工作原理如下:



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

   - (void)loadView 
{
UIView * view = [[UIView alloc ] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
//添加子视图
self.view = view;
[查看版本];
}

每次创建视图时,变为可见并在屏幕上显示,则调用-viewDidLoad。 (-viewDidAppear / -viewDidDisappear是屏幕视图的可见性)



由于我们已经偏离轨道,让我们考虑内存管理。当视图处于屏幕外时,系统将自动将视图控制器的视图属性设置为nil。问题是,该视图的所有子视图都是泄漏的。怎么会这样?嗯,每个子视图的保留计数为2(视图保留子视图,并且您的视图控制器有一个出口/ ivar到它)。当视图为nil时,该视图的保留计数为1.如果视图没有显示,视图会停留,这是没有意义的,所以你在-viewDidUnload中设置为nil(这是一个钩子每当视图设置为nil)。


I'm fairly new to UI programming on the Mac and iPhone, and I've run across something that somewhat puzzles me.

A UIViewController has 3 methods that involve the initialization of it and its view:

  1. init (and init-like methods)
  2. loadView
  3. viewDidLoad (delegate method)

I'd expect these to occur in the order above. First UIViewController is alloc'ed by some other object, then init is immediately called (or some other init method, like initWithStyle).

Only once the object is initialized would I expect it to call its own loadView function, after which the view, once loaded, calls the viewDidLoad delegate method.

This doesn't happen, for instance:

@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

Produces the console output:

0
2
3
1

The loadView and viewDidLoad methods, therefore, cannot make delegate calls, as the delegate is usually set after the call to [super init], which (as shown above) is called after loadView and viewDidLoad have run:

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

If I want to run code that sets up the ViewController in some way, notifying the delegate as it goes, should the code reside in the init method? Isn't the reason for loadView existing to allow such code to be run at the appropriate moment?

It looks to me like I'll have to create a new initWithDelegate method which sets the delegate ivar before calling [super init], is this right, or am I going about this the wrong way?

Thanks in advance :)

解决方案

The view loading system on the iPhone works like this:

When you initialize a view controller (either with -init or -initWithNibName:bundle:), it doesn't actually create and initialize the view. When you call -view for the first time, it calls -loadView. By default, -loadView just loads the view from the xib file (nibName). If you override this, though, you're responsible for creating the view and assigning it to the view controller's view property. As an example:

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

Every time you create the view, which is different from the view becoming visible and showing onscreen, it calls -viewDidLoad. (-viewDidAppear/-viewDidDisappear is for the visibility of the view on-screen)

Since we're already off-track, let's consider memory management. When the view is offscreen, the system will automatically set the view property of a view controller to nil. The problem is that all the subviews of that view are leaking. How so? Well, the retain count for each subview is 2 (views retain subviews, and your view controller has an outlet/ivar to it). When the view is nil, the retain count of that view is 1. It doesn't make sense for a view to stick around if a view isn't showing, so you set it to nil in -viewDidUnload (which is a hook for whenever the view is set to nil).

这篇关于UIViewController的顺序初始化和加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆