iPhone SDK:loadView和viewDidLoad有什么区别?


136

在iPhone应用程序中使用视图和视图控制器时,有人可以解释loadView和viewDidLoad之间的区别吗?

我的个人情况是,我将根据代码构建所有视图,如果没有任何区别,则我不会也不会使用Interface Builder。

我发现,通常当我将初始化代码添加到loadView时,最终都会得到无限的堆栈跟踪,因此我通常在viewDidLoad中完成所有子视图的构建...但是当每个执行时,我还是不清楚的放置init代码的更合适的地方是什么。理想的是初始化调用的简单图。

谢谢!

Answers:


200

我猜这里可能是问题所在,因为我已经做到了:

我发现,通常当我将初始化代码添加到loadView时,最终都会得到无限的堆栈跟踪

不要在-loadView中阅读self.view。设置它,不知道它。

如果当前未加载视图,则self.view 属性访问器将调用 -loadView。有无限的递归。

如Apple的pre-Interface-Builder示例所示,在-loadView中以编程方式构建视图的常用方法更像是这样:

UIView *view = [[UIView alloc] init...];
...
[view addSubview:whatever];
[view addSubview:whatever2];
...
self.view = view;
[view release];

我不怪您不使用IB。我对Instapaper的所有方法都坚持使用这种方法,并且发现自己比处理IB的复杂性,界面怪癖和意外的幕后行为要舒服得多。


啊,最后谢谢您的解释!我回避了分配一个临时变量,然后设置为self.view,然后释放的习惯,这似乎有点尴尬,没有必要。我现在可以理解为什么这个决定会导致我走上现在找到自己的道路。
ryan.scott

我有这样的代码,没有递归。为什么?-(void) loadView { // Frame for Hypnosis view CGRect frame = [[UIScreen mainScreen] bounds]; // Create a Hipnosis view v = [[HypnosisView alloc] initWithFrame:frame]; self.view = v;
2013年

44

loadViewUIViewController实际将加载视图并将其分配给view属性的方法。UIViewController如果要以编程方式设置view属性,这也是子类将覆盖的位置。

viewDidLoad是在加载视图后调用的方法。在调用loadView之后调用此方法。在该位置,您可以覆盖和插入代码,以在加载视图后对其进行进一步的初始设置。


14
viewDidLoad()

当您从NIB加载视图并希望在启动后执行任何自定义时使用

LoadView()

当您要以编程方式创建视图时使用(不使用Interface Builder)


这可能有一些问题,当我的视图控制器未与NIB文件关联时,我进行了测试,viewDidLoad仍被称为
ruandao

11

只需添加一些代码示例来演示NilObject所说的话:

- (void)loadView
{
    // create and configure the table view
    myTableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStyleGrouped];   
    myTableView.delegate = self;
    myTableView.dataSource = self;
    myTableView.scrollEnabled = NO;
    self.view = myTableView;

    self.view.autoresizesSubviews = YES;
}

- (void)viewDidLoad 
{
  self.title = @"Create group";

  // Right menu bar button is to Save
  UIBarButtonItem *saveButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Save" style:UIBarButtonItemStyleDone target:self action:@selector(save)];
  self.navigationItem.rightBarButtonItem = saveButtonItem;
  [saveButtonItem release];
}

4
因此,在你们两个之间,可以准确地说出loadView是我应该对控制器的self.view进行alloc / init的地方,子视图应该在viewDidLoad(或更高版本)中处理吗?
ryan.scott

2

为了防止在读取self.view时发生无限循环,请在加载视图时调用该类的super实现。超级实现将为您分配一个新的UIView。

- (void) loadView {
[super loadview];

// init code here...

[self.view addSubView:mySubview1]; //etc..

}

6
我可以发誓Apple的文档说您不应致电[super loadView];。在示例中这是矛盾的,但是我认为文档说得很对(随着时间的推移,我在示例中发现了许多错误)。[super loadView]但是,UITableViewController等需要。然而!任何后加载设置(例如,添加额外的子视图)都应在viewDidLoad中完成。
伊凡·武西卡(IvanVučica)2011年

到目前为止,我没有任何副作用地调用了[super loadView]。如果您打算将self.view设置为自己制作的内容,则可能是正确的。
futureelite7

如果在loadView中调用[super loadView],它将尝试从笔尖加载视图(如果有默认名称)。因此,您需要小心。
Ian1971'2011-4-28

并且,如果您调用[super loadView],则会在super loadView方法中初始化
self.view

1

使用loadView的最简单方法是制作某种类型的基本视图控制器,例如MyBaseViewController,它是UIViewController的子类。在它的loadView方法中,以这种方式创建视图:

-(void) loadView {
    if ([self viewFromNib]) {
        self.view = [self viewFromNib];
    } else {
        self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    }
    self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight;
    self.view.backgroundColor = [UIColor whiteColor];
}

当您需要制作一些视图控制器时,您只需使用MyBaseViewController的子类,并在其loadView控制器中像这样调用[super loadView]

//sucblass loadView
-(void) loadView {
    [super loadView];

    //rest of code like this..
    UILabel *myLabel = [[UILabel alloc] initWithFrame:myFrame];
    [self.view addSubview:myLabel];
    [myLabel release];
}

1

loadView()当要求您的控制器创建时调用self.view。你可以自己做

self.view = [UIView alloc] init...];

或控制器的父UIController类已经具有一个方法名称-loadView(),该名称将self.view初始化为空白视图。那你可以打电话

[super loadView];

我真的推荐第二种方法,因为它鼓励继承。仅当您的视图控制器未直接从UIViewController继承时。


0

Apple在viewDidLoad上给出的定义提到,在将控制器的视图加载到内存后调用该定义。简而言之,它是第一个加载的方法。

您可能正在考虑在什么条件下可以充分利用此方法?答案是,基本上您希望应用程序首先加载。例如,您可能想要不同的背景颜色,而不是白色,则可能选择蓝色。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.