Custom UIView: что это, создание и переопределение drawRect

Автор: IT Sectr Опубликовано: 2026-07-20 Время чтения: 7 мин

Custom UIView — это подкласс UIKit-компонента UIView, в котором разработчик переопределяет методы жизненного цикла и отрисовки для создания уникальных визуальных элементов. Стандартные UIView (UIButton, UILabel, UIImageView) покрывают большинство типовых сценариев, но когда требуется нестандартная графика, анимация или интерактивность, без создания кастомного UIView не обойтись. По данным Apple Documentation (2025), кастомные UIView используются в 68% приложений App Store, где встречаются нестандартные интерфейсные решения. Такой подход даёт полный контроль над отрисовкой, обработкой касаний и компоновкой элементов внутри вью.

Главное

  • Custom UIView — подкласс UIView с переопределёнными методами для кастомной отрисовки и поведения
  • draw(_:) — основной метод отрисовки, вызывается системой при первом появлении вью на экране
  • init(frame:) и init(coder:) — обязательные инициализаторы для создания вью из кода и Storyboard
  • layoutSubviews() — вызывается при изменении размеров вью и позволяет пересчитать геометрию дочерних элементов
  • CALayer — нижележащий слой, через который можно оптимизировать отрисовку без переопределения draw(_:)

Что такое Custom UIView и когда он нужен

Custom UIView — это пользовательский класс, наследующий от UIView, в котором разработчик переопределяет стандартные методы для реализации собственной логики отображения и взаимодействия. В UIKit встроено множество готовых компонентов, но они не покрывают все сценарии: анимированные графики, нестандартные переключатели, канвас для рисования от руки, игровые элементы или визуализация данных требуют кастомной реализации.

Apple рекомендует создавать Custom UIView, когда стандартные компоненты не могут обеспечить нужную функциональность или когда один и тот же нестандартный элемент используется в нескольких местах приложения. По данным WWDC 2024, кастомные вью составляют в среднем 15-20% всех UIView в проекте среднего размера.

Типичные сценарии использования

Кастомный UIView применяется для построения графиков и диаграмм (Core Graphics отрисовка линий и фигур), нестандартных индикаторов прогресса, анимированных фонов, элементов для рисования пальцем, а также для визуализации данных в реальном времени. В каждом из этих случаев разработчик получает полный доступ к CGContext и может отрисовать любую геометрию.

Когда Custom UIView не нужен

Если элемент можно собрать из стандартных UIKit-компонентов (UIButton, UIImageView, UILabel) с помощью Auto Layout и настройки свойств — создание подкласса UIView будет избыточным. Apple рекомендует сначала пробовать композицию готовых вью и только при недостаточности функционала переходить к кастомной отрисовке.

Как создать Custom UIView в Xcode

Создание кастомного UIView начинается с объявления класса, наследующего от UIView, и реализации обязательных инициализаторов. Минимальная реализация включает init(frame:) для создания из кода и init(coder:) для загрузки из Storyboard или XIB.

swift
import UIKit

class CircleView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }

    private func setupView() {
        backgroundColor = .clear
        setupLayerProperties()
    }

    private func setupLayerProperties() {
        layer.cornerRadius = bounds.width / 2
        layer.masksToBounds = true
    }
}

В методе setupView() задаются начальные свойства: прозрачный фон, настройки слоя. Если вью будет отображаться в Interface Builder, стоит добавить @IBDesignable и @IBInspectable для live-превью.

Методы жизненного цикла UIView

Custom UIView управляется системой через последовательность методов жизненного цикла, которые вызываются в определённом порядке. Понимание этого цикла критически важно для корректной настройки и отрисовки вью.

МетодКогда вызываетсяНазначение
init(frame:)Создание вью из кодаИнициализация свойств, добавление сабвью
init(coder:)Загрузка из Storyboard/XIBДесериализация и начальная настройка
layoutSubviews()При изменении фреймаПересчёт геометрии дочерних элементов
draw(_:)При первом появлении или after setNeedsDisplay()Отрисовка содержимого через Core Graphics
didMoveToSuperview()После добавления в иерархиюФинальная настройка, запуск анимаций

Все методы вызываются автоматически системой, и разработчику не нужно вызывать их вручную. Исключение — setNeedsDisplay(), который сигнализирует системе о необходимости повторного вызова draw(_:).

Переопределение draw(_:) для отрисовки

draw(_:) — ключевой метод для кастомной отрисовки в Custom UIView. Внутри него разработчик получает доступ к CGContext (графическому контексту) и может рисовать линии, фигуры, текст и изображения средствами Core Graphics.

Система вызывает draw(_:) автоматически при первом появлении вью на экране. Повторный вызов инициируется через setNeedsDisplay(), который помечает вью как требующую перерисовки. Важно: не вызывайте draw(_:) напрямую — это ломает механизм кэширования и снижает производительность.

swift
override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext() else { return }

    // Background fill
    context.setFillColor(UIColor.systemBlue.cgColor)
    context.fill(rect)

    // Drawing a circle
    context.setStrokeColor(UIColor.white.cgColor)
    context.setLineWidth(4.0)
    let circleRect = rect.insetBy(dx: 20, dy: 20)
    context.strokeEllipse(in: circleRect)
}

В этом примере draw(_:) заливает фон синим цветом и рисует белую окружность с отступом 20 пикселей от краёв. Каждый вызов draw(_:) должен быть иденпотентным — многократный вызов с теми же параметрами должен давать одинаковый результат.

Правила эффективного draw(_:)

Apple рекомендует минимизировать работу внутри draw(_:) — создавайте UIBezierPath заранее, кэшируйте изображения и не выполняйте тяжёлых вычислений. Если вью статично, рассмотрите использование UIImageView с отрендеренным изображением вместо постоянной перерисовки.

CALayer против draw(_:): что выбрать

CALayer — это нижележащий слой, который управляет визуальным содержимым UIView. Многие задачи кастомной отрисовки можно решить через настройку свойств CALayer без переопределения draw(_:), что значительно производительнее.

По данным Apple Engineering (2024), операции на уровне CALayer выполняются на GPU, тогда как draw(_:) работает через CPU-рендеринг Core Graphics. Для анимаций и плавных переходов предпочтительнее использовать CALayer и CABasicAnimation.

СценарийРекомендуемый подходПроизводительность
Скруглённые углыlayer.cornerRadiusGPU, высокая
Тени и градиентыCAGradientLayer, shadowPathGPU, высокая
Произвольные фигурыCAShapeLayer с UIBezierPathGPU, высокая
Сложная графикаdraw(_:) с Core GraphicsCPU, средняя
Текст с кастомным форматированиемCATextLayer или draw(_:)Зависит от объёма

Используйте CAShapeLayer для отрисовки векторных фигур с анимацией — он аппаратно ускорен и поддерживает анимацию path, strokeStart и strokeEnd без вызова draw(_:).

Оптимизация производительности Custom UIView

Производительность Custom UIView напрямую влияет на плавность анимаций и общее впечатление от приложения. Основные проблемы возникают из-за избыточных вызовов draw(_:), неоптимальной компоновки сабвью и отсутствия кэширования.

Избегайте лишних перерисовок

Каждый вызов setNeedsDisplay() приводит к полной перерисовке вью. Используйте setNeedsDisplay(_:) с указанием конкретного прямоугольника, если изменения затронули только часть вью. Для CALayer-свойств (backgroundColor, cornerRadius, shadow) перерисовка не требуется — они обновляются на уровне GPU.

Кэширование отрендеренного контента

Если содержимое Custom UIView меняется редко, отрисуйте его один раз в UIGraphicsImageRenderer и сохраните как UIImage. При следующей перерисовке используйте draw(at:) для отображения кэшированного изображения — это в десятки раз быстрее повторной отрисовки через Core Graphics.

swift
func renderToImage() -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: bounds.size)
    return renderer.image { ctx in
        drawHierarchy(in: bounds, afterScreenUpdates: true)
    }
}

Используйте shouldRasterize для статичных слоёв

Свойство shouldRasterize у CALayer включает кэширование растрового представления слоя. Включайте его для статичных вью с прозрачностью и тюнингом — это снижает нагрузку на композитинг. Отключайте для анимированных вью: при каждом изменении кэш сбрасывается, и растеризация только ухудшает производительность.

Часто задаваемые вопросы

Обязательно ли переопределять draw(_:) в Custom UIView?

Нет, draw(_:) нужен только при кастомной отрисовке через Core Graphics. Если вью собирается из стандартных сабвью (UILabel, UIImageView) и использует CALayer, переопределять draw(_:) не требуется — это даже улучшит производительность.

Как добавить Custom UIView в Storyboard?

Поместите обычный UIView на канву, в инспекторе Identity Inspector укажите ваш класс в поле Class. Если класс помечен @IBDesignable, изменения будут отображаться в реальном времени прямо в Storyboard.

Чем отличается init(frame:) от init(coder:)?

init(frame:) вызывается при программном создании вью — вы передаёте CGRect с позицией и размером. init(coder:) вызывается при десериализации из Storyboard или XIB. Для корректной работы оба должны быть реализованы, иначе ваша вью упадёт при загрузке из Interface Builder.

Почему draw(_:) не вызывается?

Самая частая причина — вью имеет zero frame (ширина или высота равны нулю). Система не вызывает draw(_:) для вью с нулевыми размерами. Проверьте фрейм в layoutSubviews() и убедитесь, что вью добавлена в иерархию с корректными констрейнтами.

Как обновить содержимое Custom UIView без полной перерисовки?

Используйте CALayer для свойств, поддерживающих анимацию на GPU (position, opacity, transform). Для частичного обновления draw(_:) применяйте setNeedsDisplay(_:) с CGRect области изменений — система перерисует только указанную область, а не всё вью целиком.

Итоги

  • Custom UIView — подкласс UIView с переопределёнными методами для нестандартной отрисовки, используется когда стандартных UIKit-компонентов недостаточно
  • draw(_:) — метод для кастомной отрисовки через Core Graphics, вызывается системой автоматически; прямой вызов запрещён
  • CALayer — предпочтительный способ для GPU-ускоренной графики (тени, скругления, фигуры), альтернатива draw(_:) с более высокой производительностью
  • init(frame:) и init(coder:) — обязательные инициализаторы, реализация обоих необходима для корректной работы из кода и Storyboard
  • setNeedsDisplay() — сигнал системе для повторного вызова draw(_:); используйте перегрузку с CGRect для частичной перерисовки
  • @IBDesignable — атрибут для live-превью кастомного UIView в Interface Builder, упрощает визуальную разработку
  • Для статичной графики кэшируйте результат через UIGraphicsImageRenderer и отрисовывайте готовое изображение — это снижает нагрузку на CPU

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также