0

我突然想到我可能做的不对。有人告诉过我几次,该viewDidLoad方法在第一次引用self.view. 因此,下面的代码

- (id)initWithFrame:(CGRect)frame{
self = [super initWithNibName:nil bundle:nil];
if (self) {

    self.view.frame = frame;

    }
    return self;
}

执行后完成帧分配viewDidLoad

因此,内部对 self.view.frame 的任何引用viewDidLoad都不会引用正确的框架。

更重要的是,如果我对主视图 (self.view) 内的子视图使用 autoresizingMask(支柱和弹簧),任何比例间距都将基于错误的初始比例。关于 autoresizingMask 的文档指出:

当沿同一轴设置多个选项时,默认行为是在柔性部分之间按比例分配大小差异。

配置 UIViewController 的视图的正确方法是什么?viewWillAppear是否像在or方法中配置和添加子视图一样简单viewDidAppear

4

1 回答 1

0

当你问它viewUIViewController,如果视图还没有被实例化(这是你第一次问它),它需要被创建(°)。

当一个 ViewController 需要实例化它的视图时:

  • 如果 XIB 与您的 关联,UIViewController则从 XIB 加载视图。这意味着 XIB 文件未归档,并且 XIB 中描述的所有对象都已分配/实例化。因此,XIB 中的每个视图都使用alloc++ (解压缩 XIB 的解码器)initWithCoder:实例化。因此,您的每个视图都会收到消息autoreleaseNSCoderinitWithCoder:
  • 如果没有与您关联的 XIB UIViewController,它将调用其loadView方法以允许您以编程方式创建视图。在这种情况下,您可以在其中编写代码来创建视图,例如[[[UIView alloc] initWithFrame:...] autorelease]. 因此,您的视图将由代码实例化并接收initWithFrame:消息,而不是initWithCoder:方法。
  • UIViewController通过取消归档 XIB 文件或通过 中的代码创建和实例化视图之一,loadView加载视图并UIViewController接收viewDidLoad消息。

因此,每个视图首先接收initWithFrame:(如果由代码创建)或initWithCoder:(如果从 XIB 创建)消息,然后一旦创建了UIViewController's 的所有视图层次结构,它本身就会接收消息。总是按这个顺序。viewUIViewControllerviewDidLoad


@implementation YourCustonUIView
- (id)initWithCoder:(NSCoder*)decoder
{
  // here the view is being allocated from the XIB. "alloc" as been called, "initWithCoder" is in progress
  // frame is not set at this line, but as soon as we call the super implementation…
  self = [super initWithCoder:decoder];
  if (self)
  {
    // Here all the properties of the view set in the XIB file (thru the inspector) are now applied
    // Including the frame of the view (and its backgroundColor and all what you set thru IB)
    // so self.frame is initialized with the correct value here
  }
  return self;
}

- (id)initWithFrame:(CGRect)frame
{
  // here the view is being allocated from code. "alloc" as been called, "initWithFrame" is in progress
  // self.frame is not set at this line, but as soon as we call the super implementation…
  self = [super initWithFrame:frame];
  if (self)
  {
    // Here the view is initialized with its frame property
    // so self.frame is initialized with the correct value here
    // and you can initialize every other property from here
  }
  return self;
}
@end

@implementation YourCustomUIViewController
-(void)viewDidLoad
{
  // At that point, the view of your UIViewController has been loaded/created
  // (either via XIB or via the loadView method), so either its initWithCoder (if via XIB)
  // or its initWithFrame (if via loadView) has been called
  // so in either case, its frame has the right value
}

/*
// In case your YourCustomUIViewController does not have a XIB associated with it
// You have to implement this method to provide a view to your UIViewController by code
-(void)loadView
{
  // Create a view by code, and give it a frame
  UIView* rootView = [[UIView alloc] initWithFrame:CGRectMake(0,0,..., ...)];
  rootView.backgroundColor = [UIColor redColor]; // for example
  self.view = rootView;
  [rootView release];

  // at the end of this method, self.view must be non-nil of course.
}
*/
@end

(°) 另一种可能性是视图已被实例化,但后来被释放,因为您在视图不在屏幕上时收到了内存警告,因此视图使用的内存已被回收。但无论如何,视图尚未加载,必须加载/创建

于 2012-10-14T16:35:09.973 回答