iOS - 查找视图的顶部约束?

时间:2014-11-09 21:39:35

标签: ios autolayout nslayoutconstraint

我试图在代码中找到视图的顶部约束。 在storyboard中添加了顶部约束,我不想使用IBOutlet。

在以下代码中记录firstAttribute的值似乎总是返回NSLayoutAttributeHeight类型的约束。知道如何在代码中可靠地找到视图的顶级约束吗?

NSLayoutConstraint *topConstraint;

for (NSLayoutConstraint *constraint in self.constraints) {
    if (constraint.firstAttribute == NSLayoutAttributeTop) {
        topConstraint = constraint;
        break;
    }
}

7 个答案:

答案 0 :(得分:29)

您应该遍历self.constraints

,而不是遍历self.superview.constraints

self.constraints仅包含与视图相关的约束(例如,高度和宽度约束)。

这是一个代码示例:

- (void)awakeFromNib
{
  [super awakeFromNib];

  if (!self.topConstraint) {
    [self findTopConstraint];
  }
}

- (void)findTopConstraint
{
  for (NSLayoutConstraint *constraint in self.superview.constraints) {
    if ([self isTopConstraint:constraint]) {
      self.topConstraint = constraint;
      break;
    }
  }
}

- (BOOL)isTopConstraint:(NSLayoutConstraint *)constraint
{
  return  [self firstItemMatchesTopConstraint:constraint] ||
          [self secondItemMatchesTopConstraint:constraint];
}

- (BOOL)firstItemMatchesTopConstraint:(NSLayoutConstraint *)constraint
{
  return constraint.firstItem == self && constraint.firstAttribute == NSLayoutAttributeTop;
}

- (BOOL)secondItemMatchesTopConstraint:(NSLayoutConstraint *)constraint
{
  return constraint.secondItem == self && constraint.secondAttribute == NSLayoutAttributeTop;
}

答案 1 :(得分:22)

我通常在IB中设置identifier所需的约束,然后在代码中找到它(Swift):

if let index = constraints.index(where: { $0.identifier == "checkmarkLeftMargin" }) {
    checkmarkImageViewLeftMargin = constraints[index]
}

或者@Tim Vermeulen

checkmarkImageViewLeftMargin = constraints.first { $0.identifier == "checkmarkLeftMargin" }

答案 2 :(得分:3)

使用swift和UIView扩展

extension UIView {
    func findConstraint(layoutAttribute: NSLayoutAttribute) -> NSLayoutConstraint? {
        if let constraints = superview?.constraints {
            for constraint in constraints where itemMatch(constraint: constraint, layoutAttribute: layoutAttribute) {
                return constraint
            }
        }
        return nil
    }

    func itemMatch(constraint: NSLayoutConstraint, layoutAttribute: NSLayoutAttribute) -> Bool {
        if let firstItem = constraint.firstItem as? UIView, let secondItem = constraint.secondItem as? UIView {
            let firstItemMatch = firstItem == self && constraint.firstAttribute == layoutAttribute
            let secondItemMatch = secondItem == self && constraint.secondAttribute == layoutAttribute
            return firstItemMatch || secondItemMatch
        }
        return false
    }
}

答案 3 :(得分:2)

在Xcode中的检查器中设置标识符。这就是它的用途。你说它的名字。 如果这还不够,则创建IBOutlet。

答案 4 :(得分:0)

我在Swift中写了一个小扩展:

extension UIButton { var topConstraints: [NSLayoutConstraint]? { return self.constraints.filter( { ($0.firstItem as? UIButton == self && $0.firstAttribute == .top) || ($0.secondItem as? UIButton == self && $0.secondAttribute == .top) }) } }

答案 5 :(得分:0)

基于@Igor answer,我更改了一个itemMatch方法,以考虑当第一项或第二项不是UIView时。例如,当将UIView顶部约束到安全区域顶部时。

extension UIView {
    func findConstraint(layoutAttribute: NSLayoutConstraint.Attribute) -> NSLayoutConstraint? {
        if let constraints = superview?.constraints {
            for constraint in constraints where itemMatch(constraint: constraint, layoutAttribute: layoutAttribute) {
                return constraint
            }
        }
        return nil
    }

    func itemMatch(constraint: NSLayoutConstraint, layoutAttribute: NSLayoutConstraint.Attribute) -> Bool {
        let firstItemMatch = constraint.firstItem as? UIView == self && constraint.firstAttribute == layoutAttribute
        let secondItemMatch = constraint.secondItem as? UIView == self && constraint.secondAttribute == layoutAttribute
        return firstItemMatch || secondItemMatch
    }
}

答案 6 :(得分:0)

这是一种基于@Igor方法的单线扩展方法:

add_variable

[我还制作了方法签名样式以匹配Swift 3 ... 5样式,例如:

add_weight而不是extension UIView{ func constraint(for layoutAttribute: NSLayoutConstraint.Attribute) -> NSLayoutConstraint? { return superview?.constraints.first { itemMatch(constraint: $0, layoutAttribute: layoutAttribute) } } private func itemMatch(constraint: NSLayoutConstraint, layoutAttribute: NSLayoutConstraint.Attribute) -> Bool { if let firstItem = constraint.firstItem as? UIView, let secondItem = constraint.secondItem as? UIView { let firstItemMatch = firstItem == self && constraint.firstAttribute == layoutAttribute let secondItemMatch = secondItem == self && constraint.secondAttribute == layoutAttribute return firstItemMatch || secondItemMatch } return false } } 。 ]