web-dev-qa-db-fra.com

iOS - Trouver la contrainte supérieure pour une vue?

J'essaie de trouver la contrainte supérieure de la vue dans le code . La contrainte supérieure est ajoutée dans le storyboard et je ne souhaite pas utiliser un IBOutlet.

L'enregistrement de la valeur de firstAttribute dans le code suivant semble toujours renvoyer une contrainte de type NSLayoutAttributeHeight. Avez-vous une idée de la manière dont je pourrais trouver de manière fiable une contrainte maximale d’une vue dans le code?

NSLayoutConstraint *topConstraint;

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

Au lieu d'itérer à travers self.constraints, vous devriez effectuer une itération à travers self.superview.constraints.

Le self.constraints contient uniquement des contraintes liées à la vue uniquement (par exemple, des contraintes de hauteur et de largeur).

Voici un exemple de code de ce à quoi cela pourrait ressembler:

- (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;
}
28
JRG-Developer

Je règle généralement une identifier d'une contrainte requise dans l'IB, puis je la trouve dans le code comme ceci (Swift):

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

OU par Tim Vermeulen

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

Utiliser Swift et l'extension 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
Igor

Définissez l'identifiant dans l'inspecteur dans Xcode. C'est pour ça. Vous l'appelez. Si cela ne suffit pas, vous créez l'IBOutlet. 

2
uchuugaka

J'écris une petite extension dans 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
Serhii Londar