Высота расширения iOS8 Today с использованием только автоматической компоновки дает разбитые ограничения

Документация Apple предлагает установить высоту Today Extensions с помощью автозапуска.

Если у виджета есть дополнительный контент для отображения, вы можете полагаться на ограничения Auto Layout, чтобы соответствующим образом настроить высоту виджетов. Если вы не используете автоматический макет, вы можете использовать свойство UIViewController preferredContentSize, чтобы указать новую высоту виджета.

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

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

Установка высоты с помощью автоспуска

Я начал с нового шаблона xcode и нового шаблона расширения. Единственное, что я добавил в TodayViewController.m, было:

- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets {
    return UIEdgeInsetsMake(0, 0, 0, 0);
}

Примечание. Я все еще получаю эту проблему, если просто использую поля по умолчанию.

Я ограничил высоту надписи, центрировал метку в контейнере и ограничил высоту контейнера такой же, как высота метки:

Constrained Height

Это должно привести к метке, заполняющей контейнер на указанной высоте без конфликтов ограничений. Вместо этого я получаю конфликт ограничений:

2014-09-28 10:27:39.254 TodayExtension[61090:2672196] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x7f8b8b62c670 V:[UILabel:0x7f8b8b62d9b0'Hello World'(124)]>",
    "<NSLayoutConstraint:0x7f8b8b583020 UIView:0x7f8b8b62d6e0.height == UILabel:0x7f8b8b62d9b0'Hello World'.height>",
    "<NSLayoutConstraint:0x7f8b8b5888a0 'UIView-Encapsulated-Layout-Height' V:[UIView:0x7f8b8b62d6e0(667)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7f8b8b62c670 V:[UILabel:0x7f8b8b62d9b0'Hello World'(124)]>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.

Как он нарушает ограничения, на самом деле это выглядит так, как будто я хочу: Constrained Height View

Однако в других проектах он решает разбить другие ограничения и не выглядит корректным. Кроме того, обратите внимание: если я попытаюсь изменить приоритет ограничения высоты, это приведет к сбою Xcode. Так что весело.

Не сдерживающая высота

Я надеялся, что, поскольку сдерживание высоты не сработало, возможно, если бы я не ограничивал высоту контейнера в subviews, возможно, он вычислил требуемую высоту для размещения подзонов и правильно настроил бы.

Я центрировал subview и ограничивал его высоту: i.imgur.com/PwLmhj9.png

Это просто привело к расширению, которое использует всю высоту центра уведомлений, и мой размер с правильным размером по вертикали:

i.imgur.com/kKXlocu.png

Если я не центризуюсь, но вместо этого фиксирую вертикальное пространство в верхней макете, я получаю то же самое, за исключением того, что subview привязан к вершине (но контейнер по-прежнему огромен).

Что дает?

Я знаю, что могу просто использовать preferredContentSize, но тогда почему Apple скажет, что его можно установить с помощью ограничений Auto Layout? Что я делаю неправильно?

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

Ответ 1

После некоторых экспериментов и спотыкания "что такое NSLayoutConstraint "UIView-Encapsulated-Layout-Height" и как мне заставить заставить его пересчитать чистое значение" Я решил, что вы можете обойти эту проблему, используя "Высота" и "Равные высоты" ИЛИ "Высота" и "Верхнее и нижнее" "Вертикальное пространство" (как было предложено Guilherme Sprint), а затем уменьшая "Приоритет" ограничения высоты до 999.

Height Constraint with Reduced Priority

Это не тот ответ, на который я надеялся, но он определяет высоту контейнера с помощью автоматической компоновки подзаголовка и избегает любых предупреждений о сломанных ограничениях.

Мое совершенно ненаучное предположение/предположение/вывод заключается в том, что iOS правильно смотрит на ограничения макета, чтобы определить высоту представления контейнера. Затем он добавляет новое ограничение, которое имеет ту же высоту, что и только что вычисленное, но теперь это ограничивает высоту. Уменьшение приоритета на исходном указателе ограничения высоты означает, что сгенерированное системное ограничение выигрывает и не генерируется предупреждение (хотелось бы узнать больше об этом от кого-то, кто действительно знает).

Ответ 2

Вы должны определить 5 ограничений в общей сложности, чтобы сделать Today Extension нужным вам.

4 ограничения будут определять отношение с супервидом:

  • Верхнее пространство
  • Нижнее пространство
  • Ведущее пространство
  • Трейлинг пространства

Кстати, вы должны привязать эти ограничения к полям макета, как рекомендует Apple для просмотра, и специально Today Extensions.

Пятое ограничение будет Высота для подвью. Это ограничение вместе с верхним и нижним пространствами определит точный размер вашего раздела внутри вкладки "Сегодня".

Xcode Today Extension Constraints

Просто объяснив это, ограничение высоты установит константу для subview, а верхние и нижние ограничения будут "приклеивать" супервизор к краям subview.

Today Extension running

Ответ 3

Высота метки не позволяет удовлетворить в то же время эти ограничения:

  • Минимальная высота этикетки
  • Верхнее пространство для наблюдения
  • Нижнее пространство для наблюдения

Вы можете решить эту проблему, удалив ограничение Bottom Space на Superview, а система автоопределения присвойет нижнему пространству оставшееся пространство.