Конфликты ограничений макета в виджете Today по умолчанию

Я заметил очень странное поведение в отношении автомакета в виджете «Сегодня», который я только что создал для своего приложения. Пытаясь добраться до корня проблемы, я создал простой новый проект Xcode (приложение с одним представлением) и добавил Today Extension в качестве новой цели, даже не касаясь Это.

Когда я запускаю расширение «Сегодня» на своем устройстве (iPhone 6s), первое, что происходит, это то, что в консоли возникают конфликты ограничений макета:

2016-05-03 18:17:22.216 TodayExtension[10183:4611907] 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. 
(
    "<_UILayoutSupportConstraint:0x15c665320 V:[_UILayoutGuide:0x15c6657b0(0)]>",
    "<_UILayoutSupportConstraint:0x15c663890 V:|-(0)-[_UILayoutGuide:0x15c6657b0]   (Names: '|':UIView:0x15c6642a0 )>",
    "<_UILayoutSupportConstraint:0x15c666010 V:[_UILayoutGuide:0x15c666380(0)]>",
    "<_UILayoutSupportConstraint:0x15c666ed0 _UILayoutGuide:0x15c666380.bottom == UIView:0x15c6642a0.bottom>",
    "<NSLayoutConstraint:0x15c666b80 V:[_UILayoutGuide:0x15c6657b0]-(NSSpace(8))-[UILabel:0x15c6617c0'Hello World']>",
    "<NSLayoutConstraint:0x15c666bd0 V:[UILabel:0x15c6617c0'Hello World']-(NSSpace(8))-[_UILayoutGuide:0x15c666380]>",
    "<NSLayoutConstraint:0x15c552820 'UIView-Encapsulated-Layout-Height' V:[UIView:0x15c6642a0(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x15c666bd0 V:[UILabel:0x15c6617c0'Hello World']-(NSSpace(8))-[_UILayoutGuide:0x15c666380]>

Вы заметите, что последним из ограничений в списке является UIView-Encapsulated-Layout-Height, который устанавливает высоту 0 в представлении. Я проверил и понял, что указанное представление является корневым представлением самого виджета. Так что по какой-то причине, которая находится за пределами моего понимания, система внутренне создает ограничение высоты 0 пикселей, которое конфликтует с настройкой представления в Interface Builder. (Как вы увидите, когда вы создадите новое сегодняшнее расширение в Xcode, там нет ничего, кроме UILabel, прикрепленного к каждой стороне корневого представления виджета.)

Обычно я бы сказал, что это огромная ошибка iOS, но, поскольку это по умолчанию шаблон Apple для создания виджетов Today, я просто не могу поверить, что он сломан. Есть идеи, что вызывает такое противоречивое поведение и как его исправить (правильно)?


Чего я в основном пытаюсь достичь с помощью щедрости...

... состоит в том, чтобы выяснить, существует ли надежный способ использовать автомакет в виджете Today без введения нескольких обходных путей и "грязных хаков" что вы не будете использовать в обычном приложении. (Если вы в конечном итоге добавите множество ограничений, создающих фиксированные фреймы и не позволяющих содержимому динамически увеличиваться, это не совсем идея Autolayout, не так ли?)


Тесно связанный вопрос, который является частью проблемы и может дать подсказку:
Непоследовательное поведение виджета Today нарушает ограничения высоты подпредставления


person Mischa    schedule 03.05.2016    source источник
comment
Вы пытались добавить маржу на widgetMarginInsetsForProposedMarginInsets ?   -  person Aadil Keshwani    schedule 02.06.2016
comment
Да, я сделал. Это объясняется в другом вопросе, который я связал выше.   -  person Mischa    schedule 02.06.2016
comment
@ EICaptainv2.0: Спасибо за попытку помочь. Но прежде всего, если я удалю нижнее ограничение, виджет «Сегодня» больше не будет расти вместе с содержимым метки (если вы поместите 10 строк текста внутри метки, он перекроет границы виджета). И, во-вторых, я уже успешно реализовал виджет с помощью некоторых грязных хаков, но здесь я пытаюсь найти причину необходимости этих хаков и общее решение для правильной работы с Autolayout в Сегодня виджеты. Тот, который может принести пользу всему сообществу, который можно применить к любому макету виджета.   -  person Mischa    schedule 04.06.2016
comment
@ EICaptainv2.0: Еще раз спасибо за помощь. Однако было бы здорово, если бы вы не оставляли комментарии и удаляли их снова, как только я на них отвечал. Для других пользователей, читающих эту страницу, мои комментарии будут вырваны из контекста, и никто не поймет, что происходит.   -  person Mischa    schedule 04.06.2016
comment
@ Миша, это потому, что я дам подробный ответ ...   -  person EI Captain v2.0    schedule 04.06.2016
comment
@ EICaptainv2.0: Вы можете дать ответ и оставить свои комментарии. Потому что предоставление ответа не решит проблему, из-за которой раздел комментариев здесь становится беспорядочным и запутанным, если вы просто удаляете комментарии в середине, на которые ответили другие пользователи.   -  person Mischa    schedule 04.06.2016


Ответы (2)


В некоторых стандартных подклассах Apple UIView они создаются с нулевым размером. Вам нужно настроить свои NSLayoutConstraint так, чтобы они правильно реагировали на этот начальный размер. В прошлом я делал верхние и нижние ограничения неравенством, чтобы остальные ограничения могли иметь правильный размер и не нарушать макет.

Пример: сделайте нижнее ограничение (<NSLayoutConstraint:0x15c666bd0 V:[UILabel:0x15c6617c0'Hello World']-(NSSpace(8))-[_UILayoutGuide:0x15c666380]>) LessThanOrEqualTo со значением constant 8.0.

person bsmith11    schedule 03.05.2016
comment
Когда я меняю нижнее ограничение с «Равно» на «Меньше или равно», конфликты в журнале исчезают, да, но тогда позиционирование метки непоследовательно: при первом запуске виджета текст Hello World вертикально центрируется между заголовком моего виджета. и заголовок следующего виджета. Но когда я скрываю центр уведомлений и снова смахиваю его вниз, текст внезапно подскакивает на пару пикселей вверх и теперь оказывается ближе к заголовку моего собственного виджета. Таким образом, кажется, что изменение нижнего ограничения всего лишь переносит проблему (ошибку?) в другое место. - person Mischa; 03.05.2016
comment
Вы можете добавить дополнительное нижнее ограничение EqualTo к 8.0 и присвоить ему более низкий приоритет. Таким образом, он ломается, когда это необходимо, но также заставляет нижний интервал быть 8.0, когда это возможно. - person bsmith11; 03.05.2016
comment
Это на самом деле делает работу. Тем не менее, мне действительно кажется, что я исправляю здесь системную ошибку с помощью грязного хака. Я просто не могу поверить, что базовый Autolayout (ограничение вида сверху вниз) не работает для стандартного шаблона виджета Apple Today! - person Mischa; 03.05.2016
comment
(Я столкнулся с еще несколькими аномалиями, связанными с автомакетом и пользовательским интерфейсом в целом, при создании виджета «Сегодня», и это действительно сводит меня с ума! Я бы назвал себя продвинутым во всех аспектах автомакета, и мне кажется, что половина обычных правил автомакета не применяются к виджету «Сегодня». Например, другой набор законов природы в параллельной вселенной или что-то в этом роде. /2062785) - person Mischa; 03.05.2016

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

person PaulWall43    schedule 23.06.2016