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 садржи много готових компоненти, али one не покривају све сценарије: анимирани графикони, нестандардни прекидачи, платно за цртање руком, гејминг елементи или визуелизација података захтевају прилагођену имплементацију.

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 за преглед уживо.

Методе животног циклуса UIView-а

Custom UIView се управља од стране система кроз секвенцу метода животног циклуса које се позивају одређеним редоследом. Разумевање овог циклуса је кључно за правилно подешавање и цртање приказа.

МетодаКада се позиваНамена
init(frame:)Креирање приказа из кодаИницијализација својстава, додавање подређених приказа
init(coder:)Учитавање из Storyboard/XIBДесеријализација и почетно подешавање
layoutSubviews()При промени оквираПрерачунавање геометрије подређених елемената
draw(_:)При првом појављивању или након 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 }

    // Попуњавање позадине
    context.setFillColor(UIColor.systemBlue.cgColor)
    context.fill(rect)

    // Цртање круга
    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 са UIBezierPath-омGPU, високе
Сложена графикаdraw(_:) са Core Graphics-омCPU, средње
Текст са прилагођеним форматирањем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(_:) не позива?

Најчешћи разлог — приказ има нулти оквир (ширина или висина су нула). Систем не позива 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 — атрибут за преглед уживо Custom UIView-а у Interface Builder-у, поједностављује визуелни развој
  • За статичну графику кеширајте резултат кроз UIGraphicsImageRenderer и цртајте готову слику — смањује оптерећење CPU-а

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође