Как использовать константу NSNumber или CGFloat в языке визуальных форматов Autolayout?

Я пытаюсь установить верхнее и нижнее paddings для представления в Autolayout, используя язык визуального формата. Код компилируется и работает, если я пишу paddings как целые числа в строке визуального формата, но он терпит неудачу, когда я пытаюсь заменить его константой. Вот ошибка, которую я получаю:

Завершение приложения из-за неперехваченного исключения "NSInvalidArgumentException", причина: "Невозможно разобрать ограничение format: Невозможно установить пространство, равное ширине или высоте зрения. Возможно, вы хотите использовать представление в качестве разделителя? [View1] [спейсер (== view1)] [view2] V: | -kTopAndBottomPadding- [messageTextView] -kTopAndBottomPadding- |

И это мой код.

CGFloat const SPMTVC_kTopAndBottomPadding = 5.0;
// ...

// Create my own NSDictionary of variable bindings.
NSDictionary *variableBindings = @{@"messageTextView" : _messageTextView,
    @"contentView" : self.contentView,
    @"kTopAndBottomPadding" : [NSNumber numberWithFloat:SPMTVC_kTopAndBottomPadding]};

// Constraints in the horizontal axis.
// Basically just pins the view to the left and right of superview.
NSMutableArray *constraints = [[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:|-0-[messageTextView(==contentView)]-0-|"
    options:NSLayoutFormatAlignAllLeading
    metrics:nil
    views:variableBindings] mutableCopy];

// Constraints in vertical axis, give 5-point padding from superview top & bottom.
[constraints addObjectsFromArray:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-kTopAndBottomPadding-[messageTextView]-kTopAndBottomPadding-|"
    options:NSLayoutFormatAlignAllTop
    metrics:nil
    views:variableBindings]];

for (NSLayoutConstraint *constraint in constraints) {
    [self.contentView addConstraint:constraint];
}

Я думаю, что сообщение об ошибке означает, что компилятор считает, что kTopAndBottomPadding является UIView, когда он NSNumber, как определено в словаре. Есть ли способ сделать это правильно?

Ответ 1

Это словарь словаря показателей. Например, если вы хотите использовать "padding" как константу в вашей строке VFL, сделайте что-то вроде этого:

[constraints addObjectsFromArray:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-padding-[messageTextView]-kTopAndBottomPadding-|"
    options:NSLayoutFormatAlignAllTop
    metrics:@{@"padding":@5}
    views:variableBindings]];

Ответ 2

Вам нужно передать kTopAndBottomPadding в словаре показателей, а не в словарь заметок.

Кроме того, вы можете просто использовать метод addConstraints: вместо того, чтобы возиться с изменяемыми массивами и циклами for/in.

CGFloat const SPMTVC_kTopAndBottomPadding = 5.0;
// ...

NSDictionary *metrics = @{
    @"kTopAndBottomPadding" : @(SPMTVC_kTopAndBottomPadding)
};
NSDictionary *views = @{
    @"messageTextView" : _messageTextView,
    @"contentView" : self.contentView
};

[self.contentView addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"H:|-0-[messageTextView(==contentView)]-0-|"
    options:NSLayoutFormatAlignAllLeading
    metrics:metrics views:views]];

[self.contentView addConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"V:|-kTopAndBottomPadding-[messageTextView]-kTopAndBottomPadding-|"
    options:NSLayoutFormatAlignAllTop
    metrics:metrics views:views]];