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

Приведи пример стандартной библиотеки когда bounds будет отличен от 0 по x или y

1.0 Junior🔥 71 комментариев
#UIKit и верстка

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

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

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

Когда bounds.origin отличается от нуля в стандартной библиотеке UIKit

В стандартной библиотеке UIKit наиболее классический и распространённый пример, когда bounds.origin (то есть bounds.x или bounds.y) не равен нулю — это использование UIScrollView и его наследников, таких как UITableView или UICollectionView.

Концептуальное объяснение

bounds представляет собой прямоугольник, описывающий положение и размер содержимого внутри собственной системы координат view. frame — это прямоугольник в системе координат родительского view. Когда вы скроллируете содержимое внутри UIScrollView, его bounds.origin изменяется, чтобы отразить текущее смещение видимой области относительно внутреннего содержимого. frame.origin при этом остаётся неизменным (обычно он определяет положение скролл-вью в интерфейсе).

Простая аналогия: Представьте лист бумаги (контент) внутри фиксированной рамки (скролл-вью). Когда вы двигаете лист бумаги под рамкой, положение рамки относительно стены (frame) не меняется, но положение видимой части рамки относительно самого листа (bounds) изменяется.

Пример с UIScrollView

Рассмотрим конкретный пример с кодом:

import UIKit

class ScrollViewExampleViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1. Создаем UIScrollView
        let scrollView = UIScrollView(frame: CGRect(x: 50, y: 50, width: 200, height: 200))
        scrollView.backgroundColor = .lightGray
        view.addSubview(scrollView)

        // 2. Создаем большое содержимое (ContentView)
        let contentView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
        contentView.backgroundColor = .systemBlue
        scrollView.addSubview(contentView)

        // 3. Устанавливаем contentSize скролл-вью равным размеру содержимого
        scrollView.contentSize = CGSize(width: 400, height: 400)

        // 4. Изначально bounds.origin равен (0, 0)
        print("Начальные bounds: \(scrollView.bounds)")
        // Вывод: Начальные bounds: (0.0, 0.0, 200.0, 200.0)

        // 5. Прокручиваем содержимое, например, на 100 точек по вертикали
        scrollView.contentOffset = CGPoint(x: 0, y: 100)

        // 6. Теперь bounds.origin.y стал равен -100!
        print("Bounds после скролла: \(scrollView.bounds)")
        // Вывод: Bounds после скролла: (0.0, -100.0, 200.0, 200.0)
    }
}

Ключевые моменты в примере:

  • contentOffset: Это свойство UIScrollView, которое напрямую влияет на bounds.origin. Установка contentOffset.y = 100 означает "показывать пользователю часть содержимого, которая начинается на 100 пикселей ниже его верхней границы". В системе координат скролл-вью это отражается как смещение его внутреннего прямоугольника (bounds) на -100 по оси Y.
  • Инверсия знака: contentOffset и bounds.origin связаны обратной зависимостью: bounds.origin = -contentOffset. Это логично, так как если мы отодвинули содержимое вниз на 100 точек (contentOffset.y = 100), то видимая область скролл-вью относительно этого содержимого теперь начинается выше на 100 точек (bounds.origin.y = -100).
  • frame остается постоянным: В этом примере scrollView.frame.origin всегда равен (50, 50) — его положению на экране родительского view.

Другие практические случаи

Помимо скроллинга, нестандартный bounds.origin может встретиться в других, менее частых, но важных сценариях:

  1. Кастомные трансформации view: Применение нестандартных трансформаций (например, через transform свойство) может внутренне пересчитать bounds, хотя на практике это редко приводит к изменению origin.
  2. Работа с внутренними компонентами системы: В некоторых сложных случаях, например, при реализации собственного контейнера с виртуальным пространством (аналог UIScrollView), вы будете управлять bounds.origin напрямую для корректного отображения субвью.
  3. UIView координаты внутри другого UIView: Когда view вложено в родительский view, который сам имеет не нулевой bounds.origin (например, родительский UIScrollView), система координат для всех его субвью уже начинается с этого смещения.

Заключение

Таким образом, UIScrollView и его семейство — это основной и практически значимый пример из стандартной библиотеки, где bounds.origin активно используется и отличается от (0, 0) для реализации механизма прокрутки. Понимание этого различия между frame и bounds является фундаментальным для корректной работы с иерархией views, расчетом положений элементов и обработкой touch events в сложных интерфейсах iOS.