2013-07-29 64 views
5

我有兩個視圖控制器,父和子。自動佈局約束和子視圖控制器

所以在viewDidLoad方法我做到以下幾點:

ChildViewController* childViewController = [[ChildViewController alloc] init]; 

[self addChildViewController:childViewController]; 

// ChildViewController sets his own constraints in viewDidLoad 
[self.view addSubview:childViewController.view]; 

[childViewController didMoveToParentViewController:self]; 

// 
// setup constraints to expand childViewController.view to 
// fill the size of parent view controller 
// 

所以基本上什麼情況是,updateViewConstraints其實是在self.view.frame == CGRectZero爲我指定的呼籲ChildViewController之前父控制器限制適用,所以,完全一樣定製loadView方法ChildViewController

translatesAutoresizingMaskIntoConstraints全部設置爲NO所有視圖。

什麼是正確的方法來設置限制在這種情況下,這樣ChildViewController父後更新自己的約束?

兩個控制器的當前日誌是相當令人沮喪,我不明白怎麼updateViewConstraints可以viewWillLayoutSubviews之前被稱爲:

App[47933:c07] ChildViewController::updateViewConstraints. RECT: {{0, 0}, {0, 0}} 
App[47933:c07] ParentViewController::updateViewConstraints 
App[47933:c07] ChildViewController:viewWillLayoutSubviews. RECT: {{0, 0}, {984, 454}} 
App[47933:c07] ChildViewController:viewDidLayoutSubviews. RECT: {{0, 0}, {984, 454}} 
+0

您需要在實際添加約束的位置顯示代碼,否則很難說出了什麼問題。 – Maarten

+0

@Maarten我解決了這個問題,並在下面發佈了答案,不確定這是我尋找的解決方案,它似乎是錯誤的,但它的工作原理。對不起,我不能發佈代碼,它的代碼太多了...... – Andy

回答

1

根據the following link,我將約束創建移動到viewWillLayoutSubviews,這是正確設置視圖邊界的地方。我覺得這個答案沒有解釋爲什麼子視圖控制器的updateViewConstraints在父視圖控制器之前調用,或者它只是我的代碼中的一些錯誤,但是這種解決方法解決了這個問題...

1
  1. 我認爲,如果你以前叫setNeedsLayoutlayoutIfNeeded方法纔有效。如果您使用setNeedsLayout代替,系統將知道在適當的時間更新。嘗試改變你的代碼。

  2. 當你添加約束到一個視圖,該視圖應自動重新佈局其子視圖,以說明新的限制。應該沒有必要呼籲setNeedsLayout,除非事情已經改變,因爲你已經添加了限制。你是否將約束添加到視圖中,如果是這樣:是否將它們添加到正確的視圖?

  3. 有一兩件事你可以嘗試是繼承UIView讓你看到只要ChildViewController.viewParentViewController.view執行新佈局的日誌消息:

    -(void) layoutSubviews { 
        [super layoutSubviews]; 
        NSLog(@"layoutSubviews was called on the following view: %@", [view description]); 
    } 
    

也許這將揭示的東西時,你的看法是否(或不)佈局他們的子視圖。

+0

對,layoutIfNeeded並沒有真正改變任何東西,如果setNeedsUpdateConstraints以前沒有使用過。 這是我目前的日誌: ChildViewController :: updateViewConstraints。 RECT:{{0,0},{0,0}} ParentViewController :: updateViewConstraints ChildViewController_view :: layoutSubviews – Andy

+0

所以子控制器先更新,然後更新父。在viewDidLoad中創建的所有約束,所以我不完全明白它是如何可能的。 – Andy

3

我有類似的情況,子控制器到可見控制器(彈出窗口)。

我定義界面生成子視圖控制器。它的viewDidLoad方法只是調用setTranslatesAutoresizingMaskIntoConstraints:NO

然後,我在子控制器上定義此方法,該控制器需要一個UIViewController參數,它是父級。 此方法將自己的定父視圖控制器和定義自己的約束條件:

- (void) addPopupToController:(UIViewController *)parent { 
    UIView *view = [self view]; 
    [self willMoveToParentViewController:parent]; 
    [parent addChildViewController:self]; 
    [parent.view addSubview:view]; 
    [self didMoveToParentViewController:parent]; 

    NSArray *horizontalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[view]-0-|" 
                      options:0 
                      metrics:nil 
                       views:NSDictionaryOfVariableBindings(view)]; 
    [parent.view addConstraints:horizontalConstraints]; 

    NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[view]-0-|" 
                      options:0 
                      metrics:nil 
                      views:NSDictionaryOfVariableBindings(view)]; 
    [parent.view addConstraints:verticalConstraints]; 
} 

然後父的UIViewController(這已經顯示了一個),當我要顯示我的孩子彈出視圖控制器裏面調用:

PopUpNotificationViewController *popup = [[self storyboard] instantiateViewControllerWithIdentifier:@"NotificationPopup"]; 
[popup addPopupToController:self]; 

將子控制器的視圖添加到父控制器視圖時,您可以定義想要的任何約束。