Важно: этот вопрос не касается добавления / удаления / изменения ограничений!

Мне нужна помощь в понимании того, почему следующий макет неоднозначен:

UIView (rootView)
|   UIView (topView)
|   UIView (bottomView)

Установка ограничений: V:|[topView][bottomView]|, и приоритет охвата контента bottomView выше, чем охват содержания topView.

Я бы понял это, если бы оба представления имели одинаковый приоритет объятия контента, но, поскольку значение выше на bottomView, я ожидаю, что оно должно сопротивляться большему увеличению.

Ниже я вставляю код, который вы можете использовать в шаблоне проекта Xcode "Single View App":

//
//  ViewController.m
//

#import "ViewController.h"

@interface ViewController ()
@property (strong, nonatomic) UIView* rootView;
@property (strong, nonatomic) UIView* topView;
@property (strong, nonatomic) UIView* bottomView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupViewHierarchy];
    [self setupIssueIrrelevantConstraints];
    [self setupIssueRelevantConstraints];
    [self bumpVerticalContentHuggingPriorityOfView:self.bottomView];
}

- (void)setupViewHierarchy {
    self.view.backgroundColor = [UIColor lightGrayColor];

    self.rootView = [UIView new];
    self.rootView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.rootView];

    self.topView = [UIView new];
    self.topView.translatesAutoresizingMaskIntoConstraints = NO;
    self.topView.backgroundColor = [UIColor greenColor];
    [self.rootView addSubview:self.topView];

    self.bottomView = [UIView new];
    self.bottomView.translatesAutoresizingMaskIntoConstraints = NO;
    self.bottomView.backgroundColor = [UIColor blueColor];
    [self.rootView addSubview:self.bottomView];
}

- (void)setupIssueIrrelevantConstraints {
    [self.rootView.widthAnchor constraintEqualToConstant:200.0].active = YES;
    [self.rootView.heightAnchor constraintEqualToConstant:200.0].active = YES;
    [self.rootView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor].active = YES;
    [self.rootView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor].active = YES;

    [self.topView.leftAnchor constraintEqualToAnchor:self.rootView.leftAnchor].active = YES;
    [self.topView.rightAnchor constraintEqualToAnchor:self.rootView.rightAnchor].active = YES;

    [self.bottomView.leftAnchor constraintEqualToAnchor:self.rootView.leftAnchor].active = YES;
    [self.bottomView.rightAnchor constraintEqualToAnchor:self.rootView.rightAnchor].active = YES;
}

- (void)setupIssueRelevantConstraints {
    [self.topView.topAnchor constraintEqualToAnchor:self.rootView.topAnchor].active = YES;
    [self.bottomView.bottomAnchor constraintEqualToAnchor:self.rootView.bottomAnchor].active = YES;
    [self.topView.bottomAnchor constraintEqualToAnchor:self.bottomView.topAnchor].active = YES;
}

- (void)bumpVerticalContentHuggingPriorityOfView:(UIView*)view {
    UILayoutPriority contentHuggingPriority = [view contentHuggingPriorityForAxis:UILayoutConstraintAxisVertical];
    contentHuggingPriority++;
    [view setContentHuggingPriority:contentHuggingPriority
                            forAxis:UILayoutConstraintAxisVertical];
}

@end

Я знаю, что такое неоднозначный макет, и для разрешения этого макета больше не требуется ограничений. Я ожидаю, что высота bottomView будет равна 0, потому что, поскольку его приоритет захвата содержимого больше, он должен сопротивляться большему росту, чем topView.

0
karolszafranski 20 Сен 2018 в 14:57

2 ответа

Лучший ответ

Проблема в том, что вы неправильно понимаете, что такое объятие контента. Речь идет о содержании .

Объятие содержимого актуально только тогда, когда представление имеет собственный размер содержимого, как и метка или кнопка.

https://developer.apple.com/documentation/uikit/uiview/1622600-intrinsiccontentsize

Объятие содержимого - это приоритет, с которым, несмотря на другие ограничения, представление должно подчиняться требованиям своего внутреннего размера содержимого. Вот и все.

Но ваши представления не имеют никакого внутреннего размера содержимого; нет смысла обниматься. Поэтому ваши настройки объятий контента бессмысленны и игнорируются.

2
matt 20 Сен 2018 в 12:34

Авторское решение:

Большое спасибо @matt. Ваш ответ мне помог. Я знал обо всем, что вы написали, за исключением того, что «отсутствие внутреннего размера содержимого» не означает, что он равен {0, 0}, но {-1, -1}, и это разница.

Подводя итог, мой макет работает, как и ожидалось, с небольшими изменениями. Я заставил его работать, заменив UIView на ZeroIntrinsicSizeView, который выглядит так:

@interface ZeroIntrinsicSizeView : UIView

@end

@implementation ZeroIntrinsicSizeView

- (CGSize)intrinsicContentSize {
    return CGSizeZero;
}

@end
0
karolszafranski 21 Сен 2018 в 15:15