在 iPhone 应用程序中使用视图和视图控制器时,任何人都可以解释 loadView 和 viewDidLoad 之间的区别吗?
我的个人背景是,我从代码构建所有视图,我不会也不会使用 Interface Builder,这应该有什么区别。
我发现,当我向 loadView 添加初始化代码时,我通常会得到无限的堆栈跟踪,因此我通常在 viewDidLoad 中构建所有子视图......但我真的不清楚每个何时执行,以及放置 init 代码的更合适的位置。 如果有一个简单的初始化调用图就更完美了。
谢谢!
我可以猜测这里可能存在什么问题,因为我已经做到了:
我发现,当我向 loadView 添加初始化代码时,我经常会得到无限的堆栈跟踪
不要在-loadView中读取self.view。仅set它,不要get它。
self.view 属性访问器调用 -loadView(如果当前未加载视图)。这就是你的无限递归。
在 -loadView 中以编程方式构建视图的常用方法,如 Apple 的 pre-Interface-Builder 示例所示,更像是这样:
UIView *view = [[UIView alloc] init...];
...
[view addSubview:whatever];
[view addSubview:whatever2];
...
self.view = view;
[view release];
我不会责怪你不使用IB。我在所有 Instapaper 中都坚持使用这种方法,并且发现自己比处理 IB 的复杂性、界面怪癖和意想不到的幕后行为更舒服。
loadView
是 UIViewController
中的方法,它将实际加载视图并将其分配给 view
属性。如果您想以编程方式设置 UIViewController
属性,这也是 view
的子类将覆盖的位置。
viewDidLoad
是加载视图后调用的方法。这是在调用 loadView 后调用的。您可以在其中覆盖和插入代码,以便在加载视图后对视图进行进一步的初始设置。
viewDidLoad()
当您从 NIB 加载视图并希望在启动后执行任何自定义时使用
loadView()
当您想以编程方式创建视图时使用(不使用 Interface Builder)
只需添加一些代码示例来演示 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];
}
为了防止读取 self.view 时发生无限循环,请在加载视图时调用类的超级实现。超级实现将为您分配一个新的 UIView。
- (void) loadView {
[super loadview];
// init code here...
[self.view addSubView:mySubview1]; //etc..
}
使用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];
}
loadView()
时,会调用
self.view
。你可以自己做,就像
self.view = [UIView alloc] init...];
或者你的控制器的父 UIController 类已经有一个方法名称
-loadView()
它将你的 self.view 初始化为空白视图。然后就可以打电话了
[super loadView];
我真的推荐第二种方法,因为它鼓励继承。仅当您的视图控制器不是直接继承自 UIViewController 时。
Apple 在 viewDidLoad 上给出的定义提到,它是在控制器的视图加载到内存后调用的。简而言之,它是第一个加载的方法。
你可能会想,这个方法在什么条件下才能得到充分利用?答案是,基本上无论您希望应用程序首先加载什么。例如,您可能想要不同的背景颜色,您可以选择蓝色而不是白色。