Ответ
Свойства frame и bounds объекта UIView описывают его прямоугольную область, но в разных системах координат.
| Свойство | Система координат | Описание | Изменение origin |
|---|---|---|---|
frame |
Система координат родительского view (superview). |
Определяет позицию и размер view относительно ее родителя. CGRect.origin — это точка (x, y) в координатах супервью. |
Перемещает view относительно родителя. |
bounds |
Внутренняя (собственная) система координат view. (0, 0) — это левый верхний угол самой view. |
Определяет внутренний размер view и видимую область ее содержимого (как «окошко»). CGRect.origin здесь называется bounds.origin. |
Сдвигает систему координат содержимого внутри view (например, для скроллинга). |
Ключевые отличия и правила:
- Зависимость:
frameявляется производным свойством. Он вычисляется на основеcenter,boundsиtransform. Прямое изменениеframeможет быть неточным, если задано вращение или скейлинг (transform). - Трансформации:
boundsне зависит отtransform. Если вы вращаете view, ееframe(описывающий ограничивающий прямоугольник) изменится, аbounds.size— останется прежним. - Использование
bounds.origin: Это мощный инструмент. Изменениеbounds.originсдвигает внутреннюю систему координат, что приводит к смещению всех дочерних view (subviews) и отрисованного содержимого (например,drawRect:). Именно так работает скроллинг вUIScrollView.
Наглядный пример:
// Создаем view размером 100x100, позиционируем ее в (50, 50) у родителя.
let greenView = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
greenView.backgroundColor = .green
print(greenView.frame) // (50.0, 50.0, 100.0, 100.0) - относительно родителя
print(greenView.bounds) // (0.0, 0.0, 100.0, 100.0) - свои внутренние координаты
// Меняем bounds.origin - сдвигаем «окошко», через которое view смотрит на свое содержимое.
greenView.bounds.origin = CGPoint(x: 20, y: 20)
// Теперь внутренняя система координат greenView сдвинута.
// Точка (0,0) в системе greenView теперь соответствует точке (20,20) в его собственной геометрии.
// Это приведет к смещению всех его subviews на 20pt влево и вверх.
print(greenView.frame) // (50.0, 50.0, 100.0, 100.0) - НЕ ИЗМЕНИЛСЯ (позиция относительно родителя та же)
print(greenView.bounds) // (20.0, 20.0, 100.0, 100.0) - origin изменился
Когда что использовать:
- Используйте
frameдля позиционирования и изменения размера view внутри ее супервью. - Используйте
boundsдля работы с внутренним содержимым, его отрисовкой (drawRect:) и расположением дочерних view. Изменяйтеbounds.originдля реализации скроллинга.