iOS - Find top constraint for a view?

蓝咒 提交于 2019-11-30 13:11:39

问题


I am trying to find the top constraint of the view in code. The top constraint is added in storyboard, and I don't want to use an IBOutlet.

Logging the value of the firstAttribute in the following code seems to always return a constraint of type NSLayoutAttributeHeight. Any idea how I could reliably find a top constraint of a view in code?

NSLayoutConstraint *topConstraint;

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

回答1:


Instead of iterating through self.constraints, you should iterate through self.superview.constraints.

The self.constraints only contain constraints related to just the view (e.g. height and width constraints).

Here's a code example of what this might look like:

- (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;
}



回答2:


I usually set an identifier of a required constraint in the IB and then find it in the code like this (Swift):

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

OR by @Tim Vermeulen

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



回答3:


Using swift and UIView extension

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
    }
}



回答4:


Set the identifier in the inspector in Xcode. That's what it's for. You name it. If that's not enough you create the IBOutlet.




回答5:


Based on @Igor answer, I changed a bit itemMatch method to consider when first item or second item is not a UIView. For example when constraint a UIView top to safe area top.

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:


I write a small extension in 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) }) } }



来源:https://stackoverflow.com/questions/26833641/ios-find-top-constraint-for-a-view

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!