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

Чем отличаются frame и bounds у UIView?

2.0 Middle🔥 191 комментариев
#UIKit и верстка

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

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

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

Разница между frame и bounds у UIView

Это фундаментальный вопрос при работе с iOS/macOS интерфейсами. frame и bounds - это два свойства типа CGRect, но они представляют разные системы координат.

Системы координат

frame определяется в системе координат родительского вью (superview). Он отвечает на вопрос: "Где находится этот вью относительно своего родителя?"

bounds определяется в собственной системе координат вью. Он отвечает на вопрос: "Какая область моего контента видна в моей собственной системе координат?"

// Пример создания view с разными frame и bounds
let childView = UIView()
childView.frame = CGRect(x: 50, y: 100, width: 200, height: 150)
childView.bounds = CGRect(x: 0, y: 0, width: 200, height: 150)

Ключевые отличия

1. Система отсчета

  • frame.origin - точка относительно родительского вью
  • bounds.origin - обычно (0, 0), но может меняться для реализации скроллинга
// Пример с смещенными bounds для скроллинга
scrollView.bounds.origin = CGPoint(x: 100, y: 50)
// Это сдвинет видимую область на 100 пунктов вправо и 50 вниз

2. Изменение размера

При изменении frame.size view масштабируется относительно центра (center):

view.frame.size = CGSize(width: newWidth, height: newHeight)
// Center остается неизменным, размер меняется

При изменении bounds.size view масштабируется относительно начала координат bounds (0,0):

view.bounds.size = CGSize(width: newWidth, height: newHeight)
// Масштабирование относительно верхнего левого угла

3. Ротация

Это самый важный и часто упускаемый аспект:

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

print(view.frame)    // Изменится! Будет описывать bounding box повернутого вью
print(view.bounds)   // Не изменится! Остается исходный прямоугольник
print(view.center)   // Не изменится при pure rotation

frame после применения трансформации представляет минимальный прямоугольник, содержащий трансформированный вью, тогда как bounds остается неизменным.

Практические примеры использования

Пример 1: Позиционирование subview

let parentView = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
let childView = UIView()

// Добавляем childView в центр parentView
childView.bounds = CGRect(x: 0, y: 0, width: 100, height: 100)
childView.center = CGPoint(x: parentView.bounds.midX, 
                          y: parentView.bounds.midY)

Пример 2: Реализация кастомного скроллинга

// Чтобы сдвинуть контент внутри вью, меняем bounds.origin
contentView.bounds.origin = CGPoint(x: offsetX, y: offsetY)

Пример 3: Рисование внутри drawRect

override func draw(_ rect: CGRect) {
    // Здесь rect - это часть bounds, которую нужно перерисовать
    // Все drawing операции используют координаты bounds
    
    let path = UIBezierPath(rect: self.bounds.insetBy(dx: 10, dy: 10))
    UIColor.blue.setFill()
    path.fill()
}

Когда что использовать

Используйте frame когда:

  • Позиционируете вью относительно родителя
  • Выравниваете вью в интерфейсе
  • Рассчитываете пересечения между вью
  • Анимируете перемещение вью

Используйте bounds когда:

  • Работаете с внутренним контентом вью
  • Реализуете скроллинг
  • Рисуете кастомную графику
  • Добавляете subviews относительно себя
  • Обрабатываете тапы и жесты

Важные нюансы

  1. Изменение bounds.origin не влияет на положение вью на экране, но влияет на положение его subviews
  2. frame является derived property - при его чтении система вычисляет его на основе bounds, center и transform
  3. При установке frame с трансформацией результат может быть неожиданным
  4. Не задавайте frame, если у вью есть нетривиальная transform - используйте center и bounds
// Плохо - может дать неожиданный результат при наличии transform
view.frame = newFrame

// Лучше - изменяем размер через bounds, позицию через center
view.bounds.size = newSize
view.center = newCenter

Заключение

Понимание разницы между frame и bounds критически важно для:

  • Корректного позиционирования элементов
  • Реализации скроллинга
  • Работы с трансформациями
  • Обработки touch событий
  • Оптимизации производительности (избегания лишних layout passes)

Проще всего запомнить: frame отвечает "где я?", bounds отвечает "что я вижу внутри себя?". Эта дихотомия лежит в основе всей геометрии UIKit/AppKit.