Custom UIView: cos'è, creazione e override di drawRect

Autore: IT Sectr Pubblicato: 2026-07-20 Tempo di lettura: 7 min

Custom UIView è una sottoclasse del componente UIKit UIView in cui lo sviluppatore esegue l'override dei metodi del ciclo di vita e di disegno per creare elementi visivi unici. Gli UIView standard (UIButton, UILabel, UIImageView) coprono la maggior parte degli scenari tipici, ma quando sono necessari grafica non standard, animazioni o interattività, la creazione di un UIView personalizzato è essenziale. Secondo Apple Documentation (2025), gli UIView personalizzati vengono utilizzati nel 68% delle applicazioni App Store che presentano soluzioni di interfaccia non standard. Questo approccio offre il controllo completo su disegno, gestione dei tocchi e disposizione degli elementi all'interno della vista.

Punti chiave

  • Custom UIView — una sottoclasse di UIView con metodi sovrascritti per disegno e comportamento personalizzati
  • draw(_:) — il metodo principale di disegno, chiamato dal sistema quando la vista appare per la prima volta sullo schermo
  • init(frame:) e init(coder:) — inizializzatori obbligatori per creare viste dal codice e dallo Storyboard
  • layoutSubviews() — viene chiamato quando la dimensione della vista cambia e permette di ricalcolare la geometria degli elementi figli
  • CALayer — il livello sottostante attraverso il quale è possibile ottimizzare il disegno senza sovrascrivere draw(_:)

Cos'è Custom UIView e quando serve

Custom UIView è una classe definita dall'utente che eredita da UIView, in cui lo sviluppatore sovrascrive i metodi standard per implementare la logica di visualizzazione e interazione personalizzata. UIKit include molti componenti integrati, ma non coprono tutti gli scenari: grafici animati, interruttori personalizzati, tela per disegno a mano libera, elementi di gioco o visualizzazione di dati richiedono un'implementazione personalizzata.

Apple consiglia di creare una Custom UIView quando i componenti standard non possono fornire la funzionalità richiesta o quando lo stesso elemento personalizzato viene utilizzato in più punti dell'applicazione. Secondo WWDC 2024, le viste personalizzate costituiscono in media il 15-20% di tutti gli UIView in un progetto di medie dimensioni.

Casi d'uso tipici

Custom UIView viene utilizzato per costruire grafici e diagrammi (disegno di linee e forme con Core Graphics), indicatori di progresso personalizzati, sfondi animati, elementi per disegnare con il dito e visualizzazione di dati in tempo reale. In ciascuno di questi casi, lo sviluppatore ottiene l'accesso completo a CGContext e può disegnare qualsiasi geometria.

Quando Custom UIView non è necessario

Se un elemento può essere assemblato da componenti UIKit standard (UIButton, UIImageView, UILabel) utilizzando Auto Layout e configurazione delle proprietà, creare una sottoclasse di UIView è eccessivo. Apple consiglia di provare prima la composizione di viste pronte e passare al disegno personalizzato solo quando la funzionalità è insufficiente.

Come creare una Custom UIView in Xcode

La creazione di una UIView personalizzata inizia con la dichiarazione di una classe che eredita da UIView e l'implementazione degli inizializzatori obbligatori. L'implementazione minima include init(frame:) per creare dal codice e init(coder:) per caricare dallo Storyboard o 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
    }
}

Nel metodo setupView() vengono impostate le proprietà iniziali: sfondo trasparente, impostazioni del layer. Se la vista verrà visualizzata in Interface Builder, vale la pena aggiungere @IBDesignable e @IBInspectable per l'anteprima live.

Metodi del ciclo di vita di UIView

Custom UIView è gestito dal sistema attraverso una sequenza di metodi del ciclo di vita che vengono chiamati in un ordine specifico. Comprendere questo ciclo è di fondamentale importanza per la corretta configurazione e il disegno della vista.

MetodoQuando viene chiamatoScopo
init(frame:)Creazione della vista dal codiceInizializzazione delle proprietà, aggiunta di sottoviste
init(coder:)Caricamento da Storyboard/XIBDeserializzazione e configurazione iniziale
layoutSubviews()Quando il frame cambiaRicalcolo della geometria degli elementi figli
draw(_:)Alla prima apparizione o dopo setNeedsDisplay()Disegno del contenuto tramite Core Graphics
didMoveToSuperview()Dopo essere stata aggiunta alla gerarchiaConfigurazione finale, avvio delle animazioni

Tutti i metodi vengono chiamati automaticamente dal sistema e lo sviluppatore non deve chiamarli manualmente. L'eccezione è setNeedsDisplay(), che segnala al sistema la necessità di chiamare nuovamente draw(_:).

Override di draw(_:) per il disegno

draw(_:) è il metodo chiave per il disegno personalizzato in Custom UIView. Al suo interno, lo sviluppatore ottiene l'accesso a CGContext (contesto grafico) e può disegnare linee, forme, testo e immagini utilizzando Core Graphics.

Il sistema chiama draw(_:) automaticamente quando la vista appare per la prima volta sullo schermo. Una chiamata successiva viene attivata da setNeedsDisplay(), che segna la vista come necessitante di ridisegno. Importante: non chiamare draw(_:) direttamente — questo rompe il meccanismo di caching e riduce le prestazioni.

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

    // Riempimento dello sfondo
    context.setFillColor(UIColor.systemBlue.cgColor)
    context.fill(rect)

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

In questo esempio, draw(_:) riempie lo sfondo di blu e disegna un cerchio bianco con un margine di 20 pixel dai bordi. Ogni chiamata a draw(_:) deve essere idempotente — chiamate multiple con gli stessi parametri devono produrre lo stesso risultato.

Regole per un draw(_:) efficace

Apple consiglia di minimizzare il lavoro all'interno di draw(_:) — create UIBezierPath in anticipo, fate la cache delle immagini e non eseguite calcoli pesanti. Se la vista è statica, considerate l'uso di UIImageView con un'immagine renderizzata anziché ridisegnare costantemente.

CALayer vs draw(_:): cosa scegliere

CALayer è il livello sottostante che gestisce il contenuto visivo di UIView. Molte attività di disegno personalizzato possono essere risolte configurando le proprietà di CALayer senza sovrascrivere draw(_:), il che è significativamente più efficiente.

Secondo Apple Engineering (2024), le operazioni a livello di CALayer vengono eseguite sulla GPU, mentre draw(_:) funziona tramite rendering Core Graphics basato su CPU. Per animazioni e transizioni fluide, è preferibile utilizzare CALayer e CABasicAnimation.

ScenarioApproccio consigliatoPrestazioni
Angoli arrotondatilayer.cornerRadiusGPU, alte
Ombre e gradientiCAGradientLayer, shadowPathGPU, alte
Forme arbitrarieCAShapeLayer con UIBezierPathGPU, alte
Grafica complessadraw(_:) con Core GraphicsCPU, medie
Testo con formattazione personalizzataCATextLayer o draw(_:)Dipende dal volume

Utilizzate CAShapeLayer per disegnare forme vettoriali con animazione — è accelerato hardware e supporta l'animazione di path, strokeStart e strokeEnd senza chiamare draw(_:).

Ottimizzazione delle prestazioni di Custom UIView

Le prestazioni di Custom UIView influiscono direttamente sulla fluidità delle animazioni e sull'esperienza utente complessiva. I problemi principali derivano da chiamate eccessive a draw(_:), layout non ottimale delle sottoviste e mancanza di caching.

Evitate ridisegni non necessari

Ogni chiamata a setNeedsDisplay() attiva un ridisegno completo della vista. Utilizzate setNeedsDisplay(_:) con un rettangolo specifico se le modifiche hanno interessato solo una parte della vista. Per le proprietà di CALayer (backgroundColor, cornerRadius, shadow), il ridisegno non è necessario — vengono aggiornate a livello di GPU.

Caching del contenuto renderizzato

Se il contenuto di Custom UIView cambia raramente, renderizzatelo una volta in UIGraphicsImageRenderer e salvate come UIImage. Al prossimo ridisegno, utilizzate draw(at:) per visualizzare l'immagine cached — è decine di volte più veloce di una nuova renderizzazione tramite Core Graphics.

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

Utilizzate shouldRasterize per i layer statici

La proprietà shouldRasterize su CALayer abilita il caching della rappresentazione raster del layer. Attivatela per viste statiche con trasparenza e ombre — questo riduce il carico di compositing. Disattivatela per viste animate: la cache si resetta a ogni modifica e la rasterizzazione degrada solo le prestazioni.

Domande frequenti

È obbligatorio sovrascrivere draw(_:) in Custom UIView?

No, draw(_:) è necessario solo per il disegno personalizzato tramite Core Graphics. Se la vista è composta da sottoviste standard (UILabel, UIImageView) e utilizza CALayer, non è necessario sovrascrivere draw(_:) — migliorerà addirittura le prestazioni.

Come aggiungere una Custom UIView allo Storyboard?

Posizionate una UIView normale sulla tela, nell'Identity Inspector specificate la vostra classe nel campo Class. Se la classe è contrassegnata con @IBDesignable, le modifiche verranno visualizzate in tempo reale direttamente nello Storyboard.

Qual è la differenza tra init(frame:) e init(coder:)?

init(frame:) viene chiamato durante la creazione programmatica della vista — si passa un CGRect con posizione e dimensione. init(coder:) viene chiamato durante la deserializzazione dallo Storyboard o XIB. Per un corretto funzionamento, entrambi devono essere implementati, altrimenti la vostra vista andrà in crash durante il caricamento da Interface Builder.

Perché draw(_:) non viene chiamato?

La ragione più comune è che la vista ha un frame zero (larghezza o altezza pari a zero). Il sistema non chiama draw(_:) per viste con dimensioni zero. Verificate il frame in layoutSubviews() e assicuratevi che la vista sia stata aggiunta alla gerarchia con constraint corretti.

Come aggiornare il contenuto di Custom UIView senza ridisegno completo?

Utilizzate CALayer per le proprietà che supportano l'animazione su GPU (position, opacity, transform). Per aggiornamenti parziali di draw(_:), utilizzate setNeedsDisplay(_:) con un CGRect dell'area modificata — il sistema ridisegnerà solo la regione specificata, non l'intera vista.

Riepilogo

  • Custom UIView — una sottoclasse di UIView con metodi sovrascritti per il disegno personalizzato, utilizzata quando i componenti UIKit standard sono insufficienti
  • draw(_:) — metodo per il disegno personalizzato tramite Core Graphics, chiamato automaticamente dal sistema; la chiamata diretta è vietata
  • CALayer — approccio preferito per la grafica accelerata da GPU (ombre, arrotondamenti, forme), un'alternativa a draw(_:) con prestazioni superiori
  • init(frame:) e init(coder:) — inizializzatori obbligatori; entrambi devono essere implementati per il corretto funzionamento dal codice e dallo Storyboard
  • setNeedsDisplay() — segnale al sistema per richiamare draw(_:); utilizzate l'overload con CGRect per il ridisegno parziale
  • @IBDesignable — attributo per l'anteprima live di Custom UIView in Interface Builder, semplifica lo sviluppo visivo
  • Per la grafica statica, fate la cache del risultato tramite UIGraphicsImageRenderer e disegnate l'immagine pronta — questo riduce il carico della CPU

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche