В чем разница между frame и bounds у UIView
Что проверяют
Понимаете ли вы, что это координаты в разных системах отсчёта, и знаете ли поведение при трансформации.
Как отвечать
Оба это CGRect, но заданы в разных системах координат:
frameописывает вид в системе координат родителя. Егоoriginэто положение относительноsuperview;boundsописывает вид в его собственной системе координат.originобычно нулевой, а размер тот же, что уframe.
Отсюда правило: frame отвечает на вопрос «где этот вид лежит внутри родителя», bounds на вопрос «как устроено пространство внутри самого вида».
Два случая, где разница становится принципиальной:
1. Прокрутка. У UIScrollView смещение содержимого это и есть bounds.origin. Прокручивая, вы двигаете не содержимое, а окно наблюдения: contentOffset и bounds.origin это одно и то же значение.
2. Трансформация. При повороте или масштабировании через transform:
boundsне меняется: внутренняя система координат вида остаётся прежней, и рисование внутри идёт как раньше;frameстановится описанным прямоугольником повёрнутого вида, то есть больше исходного и с другим положением.
Из этого следует важное практическое ограничение, о котором прямо пишет документация: при ненулевой трансформации значение frame не определено, менять его нельзя. Позицию в этом случае задают через center и bounds, а не через frame.
Что использовать: frame и center для размещения вида внутри родителя, bounds для расчётов внутри себя, для рисования в draw(_:) и для получения размеров. При работе с автоматической разметкой frame вручную вообще не трогают, его вычисляет система из ограничений.
Где спотыкаются
Меняют frame у вида с трансформацией.
Считают, что bounds.origin всегда нулевой.
Берут frame для рисования внутри вида и получают смещение.
Правят frame при включённой автоматической разметке и удивляются, что значение возвращается обратно.