web-dev-qa-db-ja.com

viewDidAppearの前にフレームを正しく設定できません

サブビューのフレームをviewDidLoadおよびviewWillAppearに設定したときに、変更が画面に反映されない理由を誰かが知っているのではないかと思っていましたが、viewDidAppearに設定すると?

私の場合、私は2つのTableViewを備えたカスタムxibをロードし、viewDidLoadでそれらをシフトダウンして、viewDidLoadに追加される別のビューのためのスペースを許可しようとしています。

問題は、フレームをviewDidLoadまたはviewWillAppearに設定すると、オブジェクトに設定され、印刷することで確認できますが、画面に反映されないことです。フレーム設定呼び出しをviewDidAppearに移動すると、すべてが期待どおりに動作します。

フレームをviewDidLoadに設定できると思うのは間違っていますか?

- (id)init {
    if ( self = [super initWithNibName:@"MyView" bundle:nil] ) {}

    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.descriptionWebView = [[[UIWebView alloc] initWithFrame:CGRectMake( 0, 0, self.view.frame.size.width, 200 )] autorelease];

    [self.view addSubview:self.descriptionWebView];

    self.tableView1.autoresizingMask = UIViewAutoresizingNone;
    self.tableView2.autoresizingMask = UIViewAutoresizingNone;

    [self.descriptionWebView loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"...." withExtension:@"html"]]];

    table1LocationWithHeader = CGRectMake( self.tableView1.frame.Origin.x, 200, self.tableView1.frame.size.width, self.tableView1.frame.size.height - 200 );
    table2LocationWithHeader = CGRectMake( self.tableView2.frame.Origin.x, 200, self.tableView2.frame.size.width, self.tableView2.frame.size.height - 200 );

    //this will NOT work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    //this will NOT work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}


- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    //this WILL work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}


//I added these after comments for stack overflow users, it seems like viewDidLayoutSubviews is the best place to set the frame

- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    //this will NOT work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    //this WILL work
    self.tableView1.frame = table1LocationWithHeader;
    self.tableView2.frame = table2LocationWithHeader;
}
41
nacross

クラスがロードされるときにviewDidLoadが呼び出されますが、UI要素は初期化されていないため、それらを参照しようとすると、viewDidLoad呼び出しとviewDidAppear呼び出しの間に発生する初期化プロセス中に上書きされます。すべてのui要素が初期化され、描画されると、viewDidAppearが呼び出されます。

viewDidLoad-コントローラーのビューがメモリにロードされた後に呼び出されます

この時点では、ビューはビュー階層内にありません。

viewWillAppear-ビューがビュー階層に追加されようとしていることをView Controllerに通知します。

繰り返しますが、ビューはまだビュー階層に追加されていません。

viewDidAppear-ビューがビュー階層に追加されたことをView Controllerに通知します。

その場合にのみ、ビューがビュー階層に追加されます。

更新

viewDidLayoutSubviewsは、実際に画面に表示される前にUIを変更する最も適切な場所です。

viewDidLayoutSubviews-ビューがサブビューをレイアウトしたことをView Controllerに通知します。

95
Leon Storey

このスレッドを参照してください layoutSubviewsはいつ呼び出されますか?
autolayoutを使用する場合、フレームワークはlayoutSubviewsを自動的に呼び出しません。それは非常に重要です。 refから:

  • initはlayoutSubviewsを呼び出しません(duh)
  • addSubview:追加されるビュー、追加されるビュー(ターゲットビュー)、およびターゲットのすべてのサブビューでlayoutSubviewsが呼び出されます。 ...


viewDidLoadにサブビューを追加すると、viewDidAppearの前にlayoutSubviewsが呼び出され、サブビューの正しいサイズを取得できます。ただし、何もしないと、viewDidAppearの後にlayoutSubviewsが呼び出されます。あなたのコード次第です。

2
BollMose

viewWillAppear()で

フレームを取得するビューに対して一度だけlayoutIfNeeded()を呼び出します。

if tableView then tableView.layoutIfNeeded()for exmple

0
Mohshin Shah