首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UIViewController初始化和加载顺序

UIViewController初始化和加载顺序
EN

Stack Overflow用户
提问于 2010-01-13 00:21:34
回答 5查看 46.5K关注 0票数 37

我对Mac和iPhone上的UI编程相当陌生,我遇到了一些让我有些困惑的东西。

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

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

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

只有在对象被初始化后,我才希望它调用自己的loadView函数,然后视图在加载后调用viewDidLoad委托方法。

这种情况不会发生,例如:

代码语言:javascript
运行
复制
@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

生成控制台输出:

代码语言:javascript
运行
复制
0
2
3
1

因此,loadView和viewDidLoad方法不能进行委托调用,因为委托通常是在调用超级init之后设置的,在loadView和viewDidLoad运行之后调用(如上面所示):

代码语言:javascript
运行
复制
UIViewControllerSubClass *someViewController = [[UIViewControllerSubclass alloc] init];
[viewController setDelegate:self];

如果我想运行以某种方式设置ViewController的代码,并按其运行时通知委托,那么代码是否驻留在init方法中?难道loadView存在的原因不是为了允许这样的代码在适当的时候运行吗?

在我看来,我需要创建一个新的initWithDelegate方法,在调用super之前设置委托ivar,这是对的,还是我这样做是错误的呢?

(预先谢谢:)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-01-13 01:16:18

iPhone上的视图加载系统的工作方式如下:

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

代码语言:javascript
运行
复制
- (void)loadView
{
   UIView *view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
   // add subviews 
   self.view = view;
   [view release];
}

每次创建视图(与视图变得可见并显示在屏幕上不同)时,它都会调用-viewDidLoad。(-viewDidAppear/-viewDidDisappear表示屏幕上视图的可见性)

既然我们已经偏离了轨道,那么让我们考虑内存管理。当视图脱离屏幕时,系统将自动将视图控制器的视图属性设置为零。问题是,该视图的所有子视图都在泄漏。怎么会这样呢?好的,每个子视图的保留计数是2(视图保留子视图,视图控制器有一个出口/ivar)。当视图为零时,该视图的保留计数为1。如果没有显示视图,则视图停留在周围是没有意义的,因此在-viewDidUnload中将视图设置为零(这是视图设置为零时的挂钩)。

票数 30
EN

Stack Overflow用户

发布于 2010-01-13 00:32:11

initWithNibName:bundle:方法是UIViewController类的指定初始化程序。

尝试重写并使用它而不是init:

代码语言:javascript
运行
复制
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
    }
    return self;
}

..。

代码语言:javascript
运行
复制
UIViewControllerSubClass *someViewController = [[UIViewControllerSubclass alloc] initWithNibName:@"UIViewControllerSubclass" bundle:nil];
票数 16
EN

Stack Overflow用户

发布于 2013-09-11 10:03:25

代码语言:javascript
运行
复制
-(void)awakeFromNib
{
}

只有当您使用故事板存储在故事板Nib中绘制的ViewController --即接口包时,才会调用。

正确的顺序是

代码语言:javascript
运行
复制
-(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时

代码语言:javascript
运行
复制
-(void)viewWillDisappear
-(void)viewDidDisappear

当返回到第一个ViewController时

代码语言:javascript
运行
复制
-(void)viewWillAppear
-(void)viewDidAppear
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2053498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档