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.frameviewDidLoadへの参照は、正しいフレームを参照しません。

さらに重要なことに、メインビュー(self.view)内のサブビューにautoresizingMask(ストラットとスプリング)を使用している場合、比例間隔は間違った初期比率に基づいてしまいます。autoresizingMaskに関するドキュメントには次のように記載されています。

同じ軸に沿って複数のオプションが設定されている場合、デフォルトの動作では、サイズの差がフレキシブル部分に比例して分散されます。

UIViewControllerのビューを構成する正しい方法は何ですか?viewWillAppearまたはviewDidAppearメソッドでサブビューを構成および追加するのと同じくらい簡単ですか?

4

1 に答える 1

0

viewitを aに依頼するときUIViewController、ビューがまだインスタンス化されていない場合 (初めて依頼する場合)、作成する必要があります (°)。

ViewController がそのビューをインスタンス化する必要がある場合:

  • XIB が に関連付けられている場合UIViewController、ビューは XIB からロードされます。これは、XIB ファイルがアーカイブ解除され、XIB に記述されているすべてのオブジェクトが割り当て/インスタンス化されることを意味します。したがって、XIB の各ビューはalloc+ initWithCoder:+を使用してインスタンス化されますautorelease(NSCoderは XIB をアーカイブ解除するデコーダです)。したがって、各ビューはinitWithCoder:メッセージを受け取ります
  • に関連付けられた XIB がない場合は、UIViewControllerそのloadViewメソッドを呼び出して、プログラムでビューを作成できるようにします。この場合、 のようなビューを作成するコードをそこに記述します[[[UIView alloc] initWithFrame:...] autorelease]。したがって、ビューはコードによってインスタンス化されinitWithFrame:、メソッドではなくメッセージを受け取りますinitWithCoder:
  • ビューが作成され、UIViewControllerXIB ファイルのアーカイブを解除するか、 のコードによってインスタンス化されるloadViewと、ビューがロードされUIViewController、メッセージが受信されviewDidLoadます。

したがって、各ビューはinitWithFrame:(コードで作成された場合) またはinitWithCoder:(XIB から作成された場合) メッセージを最初に受け取り、ビュー階層がすべてUIViewController作成viewされると、UIViewControllerそれ自体がviewDidLoadメッセージを受け取ります。いつもこの順番です。


@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

(°) もう 1 つの可能性は、ビューがインスタンス化された後、割り当てが解除されたことです。これは、ビューが画面に表示されていないときにメモリ警告を受け取ったため、ビューによって使用されていたメモリが回収されたためです。ただし、いずれにせよ、ビューはまだロードされていないため、ロード/作成する必要があります

于 2012-10-14T16:35:09.973 に答える