以编程方式设置约束

Isu*_*uru 26 objective-c uiscrollview uiviewcontroller ios nslayoutconstraint

我正在试验如何使用UIScrollView.经过多次麻烦,我终于掌握了它.但现在我似乎遇到了另一个障碍.

在这个简单的应用程序,我有一个滚动视图与和,以便它的工作,我必须设置视图的底部空间,所描述的滚动型约束,以0 在这里,它工作正常.我是通过IB做的.

现在我遇到了一个必须以编程方式完成该部分的场景.我在方法中添加了以下代码viewDidLoad.

NSLayoutConstraint *bottomSpaceConstraint = [NSLayoutConstraint constraintWithItem:self.view
                                                                             attribute:NSLayoutAttributeBottom
                                                                             relatedBy:NSLayoutRelationEqual
                                                                                toItem:self.scrollView
                                                                             attribute:NSLayoutAttributeBottom
                                                                            multiplier:1.0
                                                                              constant:0.0];
[self.view addConstraint:bottomSpaceConstraint];
Run Code Online (Sandbox Code Playgroud)

但它似乎没有用.它在控制台窗口中输出以下消息,我不知道该怎么做.

无法同时满足约束.可能至少下列列表中的一个约束是您不想要的约束.试试这个:(1)看看每个约束并试着找出你不期望的东西; (2)找到添加了不需要的约束或约束的代码并修复它.(注意:如果您看到了您不理解的NSAutoresizingMaskLayoutConstraints,请参阅UIView属性translatesAutoresizingMaskIntoConstraints的文档)("","")

有人可以告诉我该怎么做?我还在这里附加了一个演示项目,以便您可以更好地了解该问题.

更新:

首先感谢您的回复.使用答案中提到的方法,我能够使它工作.然而,它的情况略有不同.现在我正在尝试以编程方式将视图加载到viewcontroller.

如果我可以进一步解释.有2个视图控制器.第一个是a UITableViewController和第二个a UIViewController.里面那个UIScrollView.还有多个UIViews和一些视图的高度超过屏幕的正常高度.

UITableViewController显示选项列表.基于用户的选择,尤其是UIView在大量的出将被装载到UIViewControllerUIScrollView.

在这种情况下,上述方法不起作用.滚动没有发生.我是否必须做一些不同的事情,因为我是单独加载视图的?

我在这里上传了一个演示项目,以便您可以看到它的实际效果.请参阅表格视图列表中的Email.xib并选择电子邮件.

Rob*_*Rob 56

根据您的代码审核,一些​​评论:

  1. 通常,在显示视图时无需调整约束.如果您发现自己这样做,通常意味着您没有正确配置故事板(或至少,没有高效率).你真正需要设置/创建约束的唯一时间是(a)你是以编程方式添加视图(我建议的是更多的工作而不是它的价值); 或(b)您需要对约束进行一些运行时调整(参见下面第3点下的第三个项目符号).

  2. 我不是故意的,但你的项目有一堆冗余的代码.例如

    • 您正在为滚动视图设置框架,但这受到约束的约束,因此不执行任何操作(即,当应用约束时,frame将替换任何手动设置的设置).通常,在自动布局中,不要尝试frame直接更改:编辑约束.但是,无论如何都不需要改变约束,所以关键是没有实际意义.

    • 您正在为滚动视图设置内容大小,但在自动布局中,它也受(子视图的)约束的约束,因此这是不必要的.

    • 您正在为scrollview设置约束(已经为零),但是您没有将NIB中的视图添加到scrollview中,也在那里击败了任何意图.最初的问题是如何更改滚动视图的底部约束.但对此的底部约束已经为零,所以我认为没有理由再次将其设置为零.

  3. 我建议对项目进行更彻底的简化:

    • 通过在NIB中存储您的视图,您将使自己的生活更加艰难.如果你留在故事板世界里会更容易.如果你真的需要,我们可以帮你做NIB的东西,但为什么要让自己的生活如此艰难?

    • 使用单元格原型来促进表格中单元格的设计.您还可以定义从单元格到下一个场景的segue.这消除了编写任何代码didSelectRowAtIndexPathprepareForSegue代码的任何需要.显然,如果你有什么需要传递到下一个场景,一定要使用prepareForSegue,但到目前为止你所提出的并不需要,所以我在我的例子中对它进行了评论.

    • 假设您正在寻找以编程方式更改约束的实际示例,我已设置场景,以便文本视图将根据文本视图中的文本以编程方式更改其高度.和往常一样,在改变IB为我创建的现有约束时,不是迭代约束来找到有问题的约束,我认为设置IBOutlet约束和constant直接编辑约束的属性要高效得多,这就是我所做的.所以我将视图控制器设置为文本视图的委托,并写了一个textViewDidChange更新了文本视图的高度约束:

      #pragma mark - UITextViewDelegate
      
      - (void)textViewDidChange:(UITextView *)textView
      {
          self.textViewHeightConstraint.constant = textView.contentSize.height;
          [self.scrollView layoutIfNeeded];
      }
      
      Run Code Online (Sandbox Code Playgroud)

      注意,我的文本视图有两个高度约束,一个强制性的最小高度约束,以及一个中等优先级约束,我根据文本的数量在上面进行了更改.重点是它说明了以编程方式更改约束的实际示例.您根本不应该使用scrollview的底部约束,但这显示了您可能想要调整约束的实际示例.


在IB中添加滚动视图时,它将自动获得您需要的所有约束.您可能不希望以编程方式添加约束(至少在没有删除现有底部约束的情况下).

两种方法可能更简单:

  1. IBOutlet比如说,为现有的底部约束创建一个scrollViewBottomConstraint.然后就可以了

    self.scrollViewBottomConstraint.constant = 0.0;
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或者最初在底部约束为0.0的IB中创建视图,然后您根本不需要以编程方式执行任何操作.如果要布置长滚动视图及其子视图,请选择控制器,将其模拟指标从"推断"设置为"自由形式".然后你可以改变视图的大小,将scrollview的top和bottom约束设置为零,在滚动视图中布置你想要的所有内容,然后在运行时显示视图时,视图将适当调整大小,因为你已经将scrollview的顶部和底部约束定义为0.0,它将被正确调整大小.在IB中看起来有点奇怪,但它在应用程序运行时就像一个魅力.

  3. 如果您决定添加新约束,则可以以编程方式删除旧的底部约束,或者将旧的底部约束的优先级设置为尽可能低,这样您的新约束(具有更高优先级)将优先,优先不应用旧的低优先级底部约束.

但你肯定不想只添加一个新的约束.


dev*_*os1 21

可以在视图控制器中创建表示布局约束的插座.只需在界面构建器中选择所需的约束(例如,通过您正在安排的视图的测量窗格上的"选择和编辑").然后转到出口窗格并将"新建引用插座"拖到代码文件(.h或.m)中.这会将约束绑定到NSLayoutConstraint您可以从控制器访问的实例,并动态调整(通常通过constant属性,因为它根本不是常量,因此命名很差).

在此输入图像描述

(请注意,在XCode 6中,您可以双击约束以选择它进行编辑.)

在此输入图像描述

但是,在界面构建器中调整布局时要小心,因为您最终可能会删除约束并且必须将其重新绑定到插座.


Kun*_*nal 12

查看控制台信息,我觉得在添加两种相同类型的约束时会产生歧义.

因此,不要创建和添加新约束,而是尝试更新约束数组中已存在的先前约束.

for(NSLayoutConstraint *constraint in self.view.constraints)
    {
        if(constraint.firstAttribute == NSLayoutAttributeBottom && constraint.secondAttribute == NSLayoutAttributeBottom &&
           constraint.firstItem == self.view && constraint.secondItem == self.scrollView)
        {
            constraint.constant = 0.0;
        }
    }
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助

甚至Rob的回答也会奏效!