iOS - Find top constraint for a view?

前端 未结 7 1412
情深已故
情深已故 2020-12-28 16:52

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

相关标签:
7条回答
  • 2020-12-28 17:17

    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) })
        }
    }
    
    0 讨论(0)
  • 2020-12-28 17:19

    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.

    0 讨论(0)
  • 2020-12-28 17:24

    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" }
    
    0 讨论(0)
  • 2020-12-28 17:24

    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
        }
    }
    
    0 讨论(0)
  • 2020-12-28 17:29

    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;
    }
    
    0 讨论(0)
  • 2020-12-28 17:29

    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
        }
    }
    
    0 讨论(0)
提交回复
热议问题