Custom UIView: co to jest, tworzenie i nadpisywanie drawRect

Autor: IT Sectr Opublikowano: 2026-07-20 Czas czytania: 7 min

Custom UIView — to podklasa komponentu UIKit UIView, w której programista nadpisuje metody cyklu życia i rysowania, aby tworzyć unikalne elementy wizualne. Standardowe UIView (UIButton, UILabel, UIImageView) pokrywają większość typowych scenariuszy, ale gdy potrzebna jest niestandardowa grafika, animacja lub interaktywność, nie da się obejść bez utworzenia niestandardowego UIView. Według Apple Documentation (2025), niestandardowe UIView są używane w 68% aplikacji w App Store, w których występują niestandardowe rozwiązania interfejsu. Takie podejście daje pełną kontrolę nad rysowaniem, obsługą dotyku i rozmieszczeniem elementów wewnątrz widoku.

Najważniejsze

  • Custom UIView — podklasa UIView z nadpisanymi metodami do niestandardowego rysowania i zachowania
  • draw(_:) — główna metoda rysowania, wywoływana przez system przy pierwszym pojawieniu się widoku na ekranie
  • init(frame:) i init(coder:) — obowiązkowe inicjalizatory do tworzenia widoku z kodu i Storyboard
  • layoutSubviews() — wywoływana przy zmianie rozmiarów widoku i pozwala przeliczyć geometrię elementów potomnych
  • CALayer — leżąca poniżej warstwa, przez którą można zoptymalizować rysowanie bez nadpisywania draw(_:)

Co to jest Custom UIView i kiedy jest potrzebny

Custom UIView — to klasa użytkownika dziedzicząca po UIView, w której programista nadpisuje standardowe metody, aby zaimplementować własną logikę wyświetlania i interakcji. UIKit zawiera wiele gotowych komponentów, ale nie pokrywają one wszystkich scenariuszy: animowane wykresy, niestandardowe przełączniki, płótno do rysowania odręcznego, elementy gier czy wizualizacja danych wymagają niestandardowej implementacji.

Apple zaleca tworzenie Custom UIView, gdy standardowe komponenty nie zapewniają potrzebnej funkcjonalności lub gdy ten sam niestandardowy element jest używany w wielu miejscach aplikacji. Według WWDC 2024, niestandardowe widoki stanowią średnio 15-20% wszystkich UIView w projekcie średniej wielkości.

Typowe scenariusze użycia

Niestandardowy UIView jest używany do tworzenia wykresów i diagramów (rysowanie linii i kształtów w Core Graphics), niestandardowych wskaźników postępu, animowanych tła, elementów do rysowania palcem, a także do wizualizacji danych w czasie rzeczywistym. W każdym z tych przypadków programista ma pełny dostęp do CGContext i może narysować dowolną geometrię.

Kiedy Custom UIView nie jest potrzebny

Jeśli element można złożyć ze standardowych komponentów UIKit (UIButton, UIImageView, UILabel) za pomocą Auto Layout i konfiguracji właściwości — tworzenie podklasy UIView będzie zbędne. Apple zaleca najpierw próbować kompozycji gotowych widoków i dopiero w przypadku niewystarczającej funkcjonalności przechodzić do niestandardowego rysowania.

Jak utworzyć Custom UIView w Xcode

Tworzenie niestandardowego UIView zaczyna się od zadeklarowania klasy dziedziczącej po UIView i zaimplementowania obowiązkowych inicjalizatorów. Minimalna implementacja obejmuje init(frame:) do tworzenia z kodu oraz init(coder:) do ładowania ze Storyboard lub 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
    }
}

W metodzie setupView() ustawiane są początkowe właściwości: przezroczyste tło, ustawienia warstwy. Jeśli widok będzie wyświetlany w Interface Builder, warto dodać @IBDesignable i @IBInspectable do podglądu na żywo.

Metody cyklu życia UIView

Custom UIView jest zarządzany przez system za pomocą sekwencji metod cyklu życia, które są wywoływane w określonej kolejności. Zrozumienie tego cyklu jest krytyczne dla prawidłowej konfiguracji i rysowania widoku.

MetodaKiedy wywoływanaPrzeznaczenie
init(frame:)Tworzenie widoku z koduInicjalizacja właściwości, dodawanie subview
init(coder:)Ładowanie ze Storyboard/XIBDeserializacja i wstępna konfiguracja
layoutSubviews()Przy zmianie ramkiPrzeliczanie geometrii elementów potomnych
draw(_:)Przy pierwszym pojawieniu się lub po setNeedsDisplay()Rysowanie zawartości przez Core Graphics
didMoveToSuperview()Po dodaniu do hierarchiiKońcowa konfiguracja, uruchamianie animacji

Wszystkie metody są wywoływane automatycznie przez system i programista nie musi wywoływać ich ręcznie. Wyjątkiem jest setNeedsDisplay(), który sygnalizuje systemowi potrzebę ponownego wywołania draw(_:).

Nadpisywanie draw(_:) do rysowania

draw(_:) — kluczowa metoda niestandardowego rysowania w Custom UIView. Wewnątrz niej programista uzyskuje dostęp do CGContext (kontekstu graficznego) i może rysować linie, kształty, tekst i obrazy za pomocą Core Graphics.

System wywołuje draw(_:) automatycznie przy pierwszym pojawieniu się widoku na ekranie. Ponowne wywołanie inicjowane jest przez setNeedsDisplay(), który oznacza widok jako wymagający przerysowania. Ważne: nie wywołuj draw(_:) bezpośrednio — to psuje mechanizm buforowania i obniża wydajność.

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

    // Wypełnienie tła
    context.setFillColor(UIColor.systemBlue.cgColor)
    context.fill(rect)

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

W tym przykładzie draw(_:) wypełnia tło niebieskim kolorem i rysuje biały okrąg z odstępem 20 pikseli od krawędzi. Każde wywołanie draw(_:) powinno być idempotentne — wielokrotne wywołanie z tymi samymi parametrami powinno dawać ten sam wynik.

Zasady efektywnego draw(_:)

Apple zaleca minimalizowanie pracy wewnątrz draw(_:) — twórz UIBezierPath z wyprzedzeniem, buforuj obrazy i nie wykonuj ciężkich obliczeń. Jeśli widok jest statyczny, rozważ użycie UIImageView z wyrenderowanym obrazem zamiast ciągłego przerysowywania.

CALayer a draw(_:): co wybrać

CALayer — to leżąca poniżej warstwa, która zarządza zawartością wizualną UIView. Wiele zadań niestandardowego rysowania można rozwiązać poprzez konfigurację właściwości CALayer bez nadpisywania draw(_:), co jest znacznie wydajniejsze.

Według Apple Engineering (2024), operacje na poziomie CALayer są wykonywane na GPU, podczas gdy draw(_:) działa przez renderowanie CPU Core Graphics. Do animacji i płynnych przejść preferowane jest używanie CALayer i CABasicAnimation.

ScenariuszZalecane podejścieWydajność
Zaokrąglone rogilayer.cornerRadiusGPU, wysoka
Cienie i gradientyCAGradientLayer, shadowPathGPU, wysoka
Dowolne kształtyCAShapeLayer z UIBezierPathGPU, wysoka
Złożona grafikadraw(_:) z Core GraphicsCPU, średnia
Tekst z niestandardowym formatowaniemCATextLayer lub draw(_:)Zależy od objętości

Używaj CAShapeLayer do rysowania kształtów wektorowych z animacją — jest przyspieszony sprzętowo i obsługuje animację path, strokeStart i strokeEnd bez wywoływania draw(_:).

Optymalizacja wydajności Custom UIView

Wydajność Custom UIView bezpośrednio wpływa na płynność animacji i ogólne wrażenie z aplikacji. Główne problemy wynikają z nadmiernych wywołań draw(_:), nieoptymalnego rozmieszczenia subview i braku buforowania.

Unikaj zbędnych przerysowań

Każde wywołanie setNeedsDisplay() prowadzi do pełnego przerysowania widoku. Używaj setNeedsDisplay(_:) z określeniem konkretnego prostokąta, jeśli zmiany dotknęły tylko część widoku. Dla właściwości CALayer (backgroundColor, cornerRadius, shadow) przerysowanie nie jest wymagane — są aktualizowane na poziomie GPU.

Buforowanie wyrenderowanej zawartości

Jeśli zawartość Custom UIView zmienia się rzadko, wyrenderuj ją raz w UIGraphicsImageRenderer i zapisz jako UIImage. Przy następnym przerysowaniu użyj draw(at:) do wyświetlenia buforowanego obrazu — to dziesiątki razy szybsze niż ponowne rysowanie przez Core Graphics.

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

Używaj shouldRasterize dla statycznych warstw

Właściwość shouldRasterize w CALayer włącza buforowanie rastrowej reprezentacji warstwy. Włączaj ją dla statycznych widoków z przezroczystością i cieniami — to zmniejsza obciążenie compositingu. Wyłączaj dla animowanych widoków: przy każdej zmianie bufor jest resetowany, a rasteryzacja tylko pogarsza wydajność.

Często zadawane pytania

Czy konieczne jest nadpisywanie draw(_:) w Custom UIView?

Nie, draw(_:) jest potrzebny tylko przy niestandardowym rysowaniu przez Core Graphics. Jeśli widok składa się ze standardowych subview (UILabel, UIImageView) i używa CALayer, nadpisywanie draw(_:) nie jest wymagane — a nawet poprawi to wydajność.

Jak dodać Custom UIView w Storyboard?

Umieść zwykły UIView na płótnie, w inspektorze Identity Inspector wskaż swoją klasę w polu Class. Jeśli klasa jest oznaczona @IBDesignable, zmiany będą wyświetlane w czasie rzeczywistym bezpośrednio w Storyboard.

Czym różni się init(frame:) od init(coder:)?

init(frame:) jest wywoływany przy programowym tworzeniu widoku — przekazujesz CGRect z pozycją i rozmiarem. init(coder:) jest wywoływany przy deserializacji ze Storyboard lub XIB. Do prawidłowego działania oba muszą być zaimplementowane, w przeciwnym razie widok ulegnie awarii przy ładowaniu z Interface Builder.

Dlaczego draw(_:) nie jest wywoływany?

Najczęstszą przyczyną jest zero frame widoku (szerokość lub wysokość równa zero). System nie wywołuje draw(_:) dla widoków o zerowych rozmiarach. Sprawdź ramkę w layoutSubviews() i upewnij się, że widok został dodany do hierarchii z prawidłowymi ograniczeniami.

Jak zaktualizować zawartość Custom UIView bez pełnego przerysowania?

Używaj CALayer do właściwości obsługujących animację na GPU (position, opacity, transform). Do częściowej aktualizacji draw(_:) stosuj setNeedsDisplay(_:) z CGRect obszaru zmian — system przerysuje tylko wskazany obszar, a nie cały widok.

Podsumowanie

  • Custom UIView — podklasa UIView z nadpisanymi metodami do niestandardowego rysowania, używana gdy standardowe komponenty UIKit są niewystarczające
  • draw(_:) — metoda do niestandardowego rysowania przez Core Graphics, wywoływana automatycznie przez system; bezpośrednie wywołanie jest zabronione
  • CALayer — preferowany sposób do grafiki przyspieszonej na GPU (cienie, zaokrąglenia, kształty), alternatywa dla draw(_:) z wyższą wydajnością
  • init(frame:) i init(coder:) — obowiązkowe inicjalizatory, implementacja obu jest konieczna do prawidłowego działania z kodu i Storyboard
  • setNeedsDisplay() — sygnał dla systemu do ponownego wywołania draw(_:); używaj przeciążenia z CGRect do częściowego przerysowania
  • @IBDesignable — atrybut do podglądu na żywo niestandardowego UIView w Interface Builder, upraszcza rozwój wizualny
  • Do statycznej grafiki buforuj wynik przez UIGraphicsImageRenderer i rysuj gotowy obraz — to zmniejsza obciążenie CPU

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również