2015-10-06 67 views
2

我试图实现一个集合视图,其中每个单元格具有可变数量的UIButton实例,并且水平放置在首尾。即使在添加子视图之后,视图层次结构仍未准备好约束条件

因为按钮的数量是动态的,所以我在运行时实例化按钮并以编程方式添加自动布局约束(第一次尝试此操作)。

这是我的代码:

class MyCustomCell: UICollectionViewCell 
{ 
    var buttonTitles:[String]? 

    var buttons = [UIButton]() 

    override func didMoveToSuperview() 
    { 
     super.didMoveToSuperview() 

     guard let titles = buttonTitles else { 
      return 
     } 

     for button in buttons { 
      button.removeFromSuperview() 
     } 

     buttons.removeAll() 


     self.translatesAutoresizingMaskIntoConstraints = false 


     // FIRST LOOP: CREATE/ADD BUTTONS: 

     for (index, title) in titles.enumerate(){ 

      let button = UIButton(type: UIButtonType.Custom) 

      button.translatesAutoresizingMaskIntoConstraints = false 

      button.setTitle(title, forState: .Normal) 
      button.tag = index 

      addSubview(button) 
      buttons.append(button) 
     } 

     // SECOND LOOP: ADD CONSTRAINTS: 

     for (index, button) in buttons.enumerate(){ 

      // Vertical Constaints (common to all buttons) 

      button.addConstraint(
       NSLayoutConstraint(
        item: self, 
        attribute: NSLayoutAttribute.TopMargin, 
        relatedBy: NSLayoutRelation.Equal, 
        toItem: button, 
        attribute: NSLayoutAttribute.Top, 
        multiplier: 1, 
        constant: 0 
       ) 
      ) 

      button.addConstraint(
       NSLayoutConstraint(
        item: self, 
        attribute: NSLayoutAttribute.BottomMargin, 
        relatedBy: NSLayoutRelation.Equal, 
        toItem: button, 
        attribute: NSLayoutAttribute.Bottom, 
        multiplier: 1, 
        constant: 0 
       ) 
      ) 


      // Horizontal Constriants 

      if index == 0 { 

       // First - Constrain left to parent (self): 

       button.addConstraint(
        NSLayoutConstraint(
         item: self, 
         attribute: NSLayoutAttribute.LeftMargin, 
         relatedBy: NSLayoutRelation.Equal, 
         toItem: button, 
         attribute: NSLayoutAttribute.Left, 
         multiplier: 1, 
         constant: 0 
        ) 
       ) 
      } 
      else { 
       // Not first - Constrain left to previous button: 

       let previousButton = self.subviews[index - 1] 

       button.addConstraint(
        NSLayoutConstraint(
         item: previousButton, 
         attribute: NSLayoutAttribute.LeftMargin, 
         relatedBy: NSLayoutRelation.Equal, 
         toItem: button, 
         attribute: NSLayoutAttribute.Left, 
         multiplier: 1, 
         constant: 0 
        ) 
       ) 

       if index == (titles.count - 1) { 

        // Last: Constrain right 

        button.addConstraint(
         NSLayoutConstraint(
          item: self, 
          attribute: NSLayoutAttribute.RightMargin, 
          relatedBy: NSLayoutRelation.Equal, 
          toItem: button, 
          attribute: NSLayoutAttribute.Right, 
          multiplier: 1, 
          constant: 0 
         ) 
        ) 
       } 
      } 
     } 
    } 
} 

我得到这个异常抛出,当我尝试添加的第一个约束:

The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7f9702d19610 MyAppName.MyCustomCell:0x7f9703a690e0.topMargin == UIView:0x7f9702d163e0.top> 
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug. 
2015-10-06 18:39:58.863 Meeting Notes[15219:1817298] View hierarchy unprepared for constraint. 
    Constraint: <NSLayoutConstraint:0x7f9702d19610 MyAppName.MyCustomCell:0x7f9703a690e0.topMargin == UIView:0x7f9702d163e0.top> 
    Container hierarchy: 
<UIView: 0x7f9702d163e0; frame = (0 0; 97 60); gestureRecognizers = <NSArray: 0x7f96fb64b5c0>; layer = <CALayer: 0x7f96fb606880>> 
    View not found in container hierarchy: <MyAppName.MyCustomCell: 0x7f9703a690e0; baseClass = UICollectionViewCell; frame = (103 0; 97 60); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7f96fb64bcd0>> 
    That view's superview: <UICollectionView: 0x7f96fb8cc800; frame = (0 172; 1024 596); clipsToBounds = YES; autoresize = RM+BM; gestureRecognizers = <NSArray: 0x7f9701f813f0>; layer = <CALayer: 0x7f9701f865c0>; contentOffset: {0, 0}; contentSize: {1024, 182}> collection view layout: <UICollectionViewFlowLayout: 0x7f9701f8df50> 
(lldb) 

随着讨论here和其他类似的问题,这种情况发生的时候参与约束的观点不是父子关系;不过,在添加任何约束之前,我已经添加了所有子视图(我将循环分成两部分)。此外,整个代码运行在单元的内部didMovetoSuperview,因此单元本身不孤立...

我在想什么?

回答

6

看到错误消息:

当添加到一个视图,约束的项目必须是该视图的后代(或视图本身)

在你的情况下,所有的约束应该被添加到self

self.addConstraint(... 
+0

除了这个参数项应该是交换与项 –

+0

谢谢,我误读因为“一个必须是另一个的子视图”。那么,如何在按钮**之间添加约束**? –

+0

'self.addConstraint(NSLayoutConstraint(item:button1,... toItem:button2 ...))'应该有效。 – rintaro

相关问题