Конфликты NSLayoutConstraints

Я пытаюсь программно добавить кнопки в представление под NSTextField, которое уже находится в представлении. Представление было создано в IB и использует ограничения. Это NSTableCellView, но я сомневаюсь, что в данном случае это имеет значение. Мой код таков:

NSView *previousView = self.pathsField;

for( NSString *path in self.revision.paths )
{
    NSButton *pb = [[NSButton alloc] initWithFrame: bframe];

    pb.bezelStyle = NSRoundRectBezelStyle;
    [self addSubview: pb];
    pb.title = path;
    [self addConstraint: [NSLayoutConstraint constraintWithItem: pb
                                           attribute: NSLayoutAttributeTop
                                           relatedBy: NSLayoutRelationEqual
                                           toItem: previousView
                                           attribute: NSLayoutAttributeBottom
                                           multiplier: 1 constant: 2.0]];
    [buttons addObject: pb];
    bframe.origin.y += 20;
    previousView = pb;
}
self.pathButtons = buttons;

Если я возьму вызов addConstraint, кнопки будут добавлены без жалоб (просто не в нужном месте). С вызовом addConstraint я получаю много сообщений о конфликтах ограничений в консоли отладки, и некоторые из моих ограничений, созданных IB, нарушаются.

Очевидно, я делаю что-то не так. Я ожидал, что ограничение потребует, чтобы верхняя часть новой кнопки была на 2 пикселя ниже нижней части предыдущего представления или кнопки. Не похоже, что это должно вызывать какие-либо конфликты, так где я?


person Matt    schedule 05.04.2013    source источник


Ответы (2)


На самом деле вы совершаете оба вида ошибок, которые вы можете совершить с ограничениями: ваши ограничения оба конфликтуют, и неоднозначны! Избавьтесь от конфликта, установив translatesAutoresizingMaskIntoConstraints в NO, как сказал кто-то другой, но затем начните беспокоиться о двусмысленности. Вы можете успешно использовать ограничения только в том случае, если укажете все, необходимое для макета. Вы указываете вершину, но это все; вам также нужно указать передний край (слева) и, возможно, ширину и высоту (возможно, не потому, что кнопка иногда имеет собственный размер; вам придется поэкспериментировать).

person matt    schedule 06.04.2013
comment
Право на! Спасибо за помощь. TranslateAutoResizingMask был недостающим битом. После этого было просто заставить макет вести себя. - person Matt; 06.04.2013
comment
Обязательно проверьте двусмысленность! Лучший способ: сделать паузу в отладчике и произнести po [[UIWindow keyWindow] _autolayoutTrace] в командной строке консоли отладчика. - person matt; 06.04.2013
comment
Кроме того, поскольку вы также являетесь @Matt, я чувствую, что могу указать вам между Matts, что вы не принимаете (установите флажок рядом с одним из ответов на ваши вопросы). Я не говорю, что вы должны принять мой ответ (другой ответ был правильным и был первым); Я просто говорю, что люди будут более склонны помочь вам, если вы сделаете это, потому что это является одним из их основных мотивов для оказания помощи в первую очередь. - person matt; 06.04.2013

Ошибки, которые вы получаете, связаны с тем, что вы не выбрали автомакет, вызвав setTranslatesAutoresizingMaskIntoConstraints: для дочерних представлений.

NSButton *pb = [[NSButton alloc] initWithFrame: bframe];
[pb setTranslatesAutoresizingMaskIntoConstraints:NO];
person Fruity Geek    schedule 06.04.2013