← Назад к вопросам

В каких случаях bounds может быть больше frame?

1.7 Middle🔥 192 комментариев
#UIKit и верстка

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Когда bounds больше frame в iOS / UIKit

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

Основное различие:

  • Frame — это прямоугольник вью, выраженный в системе координат супервью (родителя). Он определяет положение и размер вью относительно её родителя.
  • Bounds — это прямоугольник вью, выраженный в её собственной системе координат. Его начало (origin) обычно (0, 0), а размер (size) — это внутренний размер самой вью.

Основной случай: вращение вью (Affine Transform)

Главный и наиболее частый случай, когда bounds.size становится больше frame.size, — это применение вращающего преобразования (CGAffineTransform.rotation).

Когда вы вращаете вью (например, на 45 градусов), её frame автоматически пересчитывается так, чтобы быть минимальным прямоугольником (bounding box), который может содержать повернутую вью, и всё ещё выражен в координатах супервью. Размер этого bounding box'а (frame.size) будет меньше диагонали оригинальной вью.

При этом bounds остаётся неизменным — это размер и система координат внутреннего "холста" вью. С точки зрения собственного содержимого вью, она не изменила своих размеров.

let view = UIView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
view.backgroundColor = .blue

// До трансформации:
print("Frame: \(view.frame)") // (50.0, 50.0, 100.0, 100.0)
print("Bounds: \(view.bounds)") // (0.0, 0.0, 100.0, 100.0)
// bounds.size == frame.size

// Применяем вращение на 45 градусов
view.transform = CGAffineTransform(rotationAngle: .pi / 4)

// После трансформации:
print("Frame after rotation: \(view.frame)")
// Пример: (29.3, 29.3, 141.4, 141.4) - меньшая координата, но больший размер!
print("Bounds after rotation: \(view.bounds)")
// (0.0, 0.0, 100.0, 100.0) - не изменились!

// Сравниваем размеры:
print("Frame width: \(view.frame.width)") // ~141.4
print("Bounds width: \(view.bounds.width)") // 100.0
// Теперь frame.width > bounds.width!

Почему так происходит:

  1. Физическое содержимое вью (её bounds) остаётся квадратом 100x100.
  2. Чтобы разместить этот повернутый квадрат в координатах родителя, требуется описать его ограничивающим прямоугольником (frame).
  3. Для квадрата, повернутого на 45°, диагональ становится шириной и высотой фрейма. Диагональ квадрата 100x100 равна 100 * √2 ≈ 141.4.

Таким образом, после вращения:

  • frame.size описывает габариты вью в мире родителя.
  • bounds.size описывает внутренний, "нативный" размер вью.
  • Для не-прямоугольных проекций (после вращения) frame становится больше, чтобы вместить всё содержимое bounds.

Альтернативный сценарий: отрицательный origin bounds

Есть ещё одна теоретическая возможность, при которой frame может оказаться меньше bounds, но она гораздо более экзотична. Если вручную установить bounds.origin в отрицательные координаты, это сместит систему координат внутри вью. Так как frame — это вычисляемое свойство, зависящее от bounds, center и transform, его размер может измениться при определённых условиях комбинаций.

Однако, чисто технически, прямой манипуляцией только размеров (size) bounds и frame достичь ситуации, где bounds.size > frame.size без трансформаций, нельзя. Система их синхронизирует, если transform является .identity.

Ключевые выводы для собеседования:

  1. Корректнее говорить не "bounds больше frame", а "размер bounds может быть меньше размера frame" — сравниваются именно bounds.size и frame.size.
  2. Основная причина — не идентичная трансформация вью, чаще всего вращение. Frame становится bounding box'ом для трансформированного bounds.
  3. Frame — геометрия вью в контексте родителя. Bounds — внутренняя геометрия "холста" вью. Различия в их размерах наглядно демонстрируют эту разницу.
  4. Это имеет практические последствия: например, при проверке попадания точки (point(inside:with:)) система использует bounds, а не frame. Вращённая вью будет реагировать на касания в рамках своего bounds (100x100), а не frame (~141x141).

Понимание этого нюанса критически важно для корректной работы с анимациями, кастомной отрисовкой (drawRect) и обработкой касаний в сложных иерархиях вью.

В каких случаях bounds может быть больше frame? | PrepBro