Ios 在没有nibs/xibs的UIViewController中正确使用loadView和viewDidLoad

Ios 在没有nibs/xibs的UIViewController中正确使用loadView和viewDidLoad,ios,cocoa-touch,uiviewcontroller,Ios,Cocoa Touch,Uiviewcontroller,当我在没有nib的情况下编程时,我的印象是需要调用loadView来初始化我的视图,如下所示: - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nil bundle:nil]; if (self) { // Custom initialization [self loadV

当我在没有nib的情况下编程时,我的印象是需要调用loadView来初始化我的视图,如下所示:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nil bundle:nil];
    if (self) {
        // Custom initialization
        [self loadView];
    }
    return self;
}
- (void) loadView {
    self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 367)];
    [self viewDidLoad];
}
(由于没有nib,我已将nibNameOrNil设置为nil。)

然后,我设置视图,如下所示:

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nil bundle:nil];
    if (self) {
        // Custom initialization
        [self loadView];
    }
    return self;
}
- (void) loadView {
    self.view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 367)];
    [self viewDidLoad];
}
这是在viewDidLoad中执行所有其他操作

我仍然不确定是否应该以这种方式调用loadView和viewDidLoad。他们不会被自动呼叫

令人困惑的是UIViewController类参考的文档中:

loadView讨论

永远不要直接调用此方法。视图控制器调用 当请求视图属性但当前为nil时,使用此方法。 如果手动创建视图,则必须重写此方法并 使用它创建视图。如果使用Interface Builder创建 创建视图并初始化视图控制器,即初始化 在使用initWithNibName:bundle:方法的视图中,设置nibName和 直接绑定属性,或同时创建视图和视图 接口生成器中的控制器,则不能重写此 方法

所以,如果我不应该直接调用loadView,我不明白它是如何被调用的

此方法的默认实现查找有效的nib 信息,并使用该信息加载关联的nib文件。 如果未指定nib信息,则默认实现将创建 普通UIView对象,使其成为主视图。

我不明白它是怎么工作的——创建一个痛苦视图

如果为了手动创建视图而重写此方法, 您应该这样做,并将层次结构的根视图分配给 查看属性。(您创建的视图应该是唯一的实例和视图。) 不应与任何其他视图控制器对象共享。)您的 此方法的自定义实现不应调用super

如果要对视图执行任何其他初始化,请执行以下操作: 因此,在viewDidLoad方法中。在iOS 3.0及更高版本中,您还应该 重写viewDidUnload方法以释放对 视图或其内容

好的,到目前为止还没有说明viewDidLoad是如何调用的。因此,对于viewDidLoad:

视图加载讨论

在视图控制器加载其 将关联视图存储到内存中调用此方法时不考虑 视图是存储在nib文件中还是创建的 以编程方式在loadView方法中。这种方法最常见 用于对以下视图执行其他初始化步骤: 从nib文件加载

打什么电话


由于这些方法在我的代码中没有被自动调用,我不得不自己去调用它们。但是我仍然没有从文档中清楚地了解到这样做是正确的。

正如文档所说,您不应该自己调用这些方法。

这意味着当UIKit的代码实际需要在屏幕上显示控制器的视图层次结构时,它将调用您的loadView方法

具体来说,如果任何代码试图读取视图控制器上的
view
属性,并且该属性为nil,则UIViewController的代码将调用
loadView
方法。如果您自己没有实现
loadView
,那么默认实现将退回到尝试从nib加载视图层次结构

当您尝试显示视图控制器且视图为零时,所有这些都会自动发生。(如果您的视图控制器必须卸载其视图以响应内存压力,这可能会在应用程序运行时发生多次,这是另一种“免费”的行为,您不想称自己为视图控制器)

如果没有在视图控制器中调用这些方法,则表示此视图控制器的方式肯定有问题,这会阻止UIViewController中的框架代码调用这些方法。发布代码,有人会帮你找出那个bug

但是,在尝试修复该缺陷之前,应该从代码中删除以下内容:

[self loadView]
[self viewDidLoad]
然后在您自己的
viewDidLoad
实现中,您将希望使用
[super viewDidLoad]

请记住,在
loadView
中,您唯一的责任是将self.view设置为某个有效视图。就这样。UIKit代码随后将看到这一点,并为您调用
viewDidLoad

希望对您有所帮助。

菲罗兹·拉菲尔的回答是正确的,我只想展示如何强制加载视图属性的正确方法

(void)self.view;

您不应该这样做如果你必须这样做,那就是你做错了什么,但在任何情况下都不要自己打电话给
-loadView
-viewDidLoad

我仍在思考你的答案。这肯定会影响我使用视图控制器对每个主要视图进行初始化和启动的方法。如果我能理解这一点,它将帮助我进行视图内存管理。我不明白的是如何获得对self.view属性的第一个引用。例如,如果它进入导航控制器堆栈,我的代码引用的是视图控制器,而不是视图属性。我可能需要进行实验,但我的经验告诉我这是行不通的。让我们以导航控制器为例:将一个新vc推到堆栈上,UIKit将尝试在该vc的视图中设置动画。此时,您的视图将为零,因此框架(他们的代码,而不是您的代码)将调用loadView。它似乎如您所说的那样工作。从现在起,我会密切关注的。如果loadView没有被调用,我现在有一个更好的想法需要做什么