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

ary*_*axt 19 ios autolayout nslayoutconstraint

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

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

NSLayoutConstraint *topConstraint;

for (NSLayoutConstraint *constraint in self.constraints) {
    if (constraint.firstAttribute == NSLayoutAttributeTop) {
        topConstraint = constraint;
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

JRG*_*per 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;
}
Run Code Online (Sandbox Code Playgroud)


Sof*_*ner 22

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

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

或者@Tim Vermeulen

checkmarkImageViewLeftMargin = constraints.first { $0.identifier == "checkmarkLeftMargin" }
Run Code Online (Sandbox Code Playgroud)

  • `if let constraint = constraints.filter {$ 0.identifier =="checkmarkLeftMargin"} .first {}`:) (3认同)
  • @aryaxt那里有第一个(其中:)! (2认同)
  • 如果您在界面构建器中完成所有这些操作,您还可以设置一个 Outlet。 (2认同)

Moh*_*ami 6

基于@Igor的回答,我改变了一点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
    }
}
Run Code Online (Sandbox Code Playgroud)


Igo*_*gor 5

使用 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
    }
}
Run Code Online (Sandbox Code Playgroud)