"NSInvalidArgumentException", причина: "Невозможно разобрать формат ограничения"
У меня есть subview, что я хочу держать стопы во вращающемся экране, поэтому я решил поместить тип NSLayoutConstraint:
Запуск пространства для наблюдения
Верхнее пространство для наблюдения
Кнопка Пространство для наблюдения
Я в подклассе UITableViewCell. Я написал код, но я получаю следующую ошибку:
'NSInvalidArgumentException', reason: 'Unable to parse constraint format:
self is not a key in the views dictionary.
H:[self.arrows]-5-|
Мой код в CustomCell.m:
self.arrows = [[Arrows alloc]initWithFrame:CGRectMake(self.contentView.bounds.size.width-30, self.bounds.origin.y+4, 30, self.contentView.bounds.size.height-4)];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(self.arrows, self.contentView);
NSMutableArray * constraint=[[NSMutableArray alloc]init];
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H: [self.arrows]-5-|" options:0 metrics:nil views:viewsDictionary]];
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-1-[self.arrows]" options:0 metrics:nil views:viewsDictionary]];
[constraint addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"[V: [self.arrows]-1-|" options:0 metrics:nil views:viewsDictionary]];
[self.arrows addConstraints:constraint];
Ответы
Ответ 1
Похоже, что механизм синтаксического анализа визуального форматирования autolayout интерпретирует ".
" в вашем ограничении VFL как ключPath вместо этого ключа, используя valueForKeyPath:
.
NSDictionaryOfVariableBindings(...)
будет принимать все ваши параметры в скобках и переводить их в буквенный ключ с объектом в качестве значения (в вашем случае: @{"self.arrow" : self.arrow}
). В случае VFL автозапуск считает, что у вас есть ключ с именем self
в вашем словаре словарей с подзадачом (или подобъектом), который имеет ключ arrow
,
@{
@"self" : @{ @"arrow" : self.arrow }
}
когда вы буквально хотели, чтобы система интерпретировала ваш ключ как "self.arrow
".
Обычно, когда я использую переменную getper экземпляра, как это, я обычно создаю свой собственный словарь вместо использования NSDictionaryOfVariableBindings(...)
следующим образом:
NSDictionary *views = @{ @"arrowView" : self.arrow }
или
NSDictionary *views = NSDictionaryOfVariableBindings(_arrow);
Что бы вы могли использовать представление в своем VFL без себя, и вы все еще знаете, о чем говорите:
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[arrowView]-5-|" options:0 metrics:nil views];
или
NSArray *arrowHorizConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[_arrow]-5-|" options:0 metrics:nil views];
Как правило, я научился не использовать словарные ключи с точкой (.
) в них, чтобы избежать путаницы или отладки кошмаров в системе.
Ответ 2
Мой трюк состоит в том, чтобы просто объявить локальную переменную, которая будет просто другим указателем на свойство, и поместить его в NSDictionaryOfVariableBindings
.
@interface ViewController ()
@property (strong) UIButton *myButton;
@property (strong) UILabel *myLabel;
@end
...
UIButton *myButtonP = self.myButton;
UILabel *theLabelP = self.myLabel;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(myButtonP, myLabelP);
Суффикс P
предназначен для "указателя".
Ответ 3
Самое простое решение - избегать геттеров для переменных из вашего собственного класса и переопределять переменные из суперклассов в качестве локальных переменных. Решение для вашего примера -
UIView *contentView = self.contentView;
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(_arrows, contentView);
Ответ 4
Удостоверьтесь, что вы добавили ограничения после добавления необходимого представления в основной вид. Некоторое время он получал знания, связанные с этой проблемой.