SwiftUI: cos'è, concetti chiave e View Protocol

Autore: IT Sectr Pubblicato: 2026-04-30 Tempo di lettura: 8 min

SwiftUI è un framework dichiarativo di Apple per costruire interfacce utente su tutte le piattaforme dell'ecosistema. Invece di descrivere i passaggi in modo imperativo, lo sviluppatore dichiara come dovrebbe apparire l'interfaccia e SwiftUI gestisce il suo rendering e aggiornamento. Secondo la Apple Developer Documentation (2025), SwiftUI supporta iOS 15+, iPadOS 15+, macOS 12+, watchOS 8+ e tvOS 15+ e utilizza il View Protocol come blocco di costruzione di base per tutti i componenti dell'interfaccia.

Punti chiave

  • SwiftUI è un framework dichiarativo di Apple in cui lo sviluppatore descrive l'interfaccia e gli aggiornamenti vengono eseguiti automaticamente.
  • View Protocol con la proprietà body è la base di qualsiasi componente UI SwiftUI, restituendo una descrizione dello schermo tramite composizione di viste.
  • Property Wrappers — @State, @Binding, @ObservedObject, @StateObject — gestiscono lo stato e attivano il ridisegno quando i dati cambiano.
  • NavigationStack (iOS 16+) è un'API di navigazione moderna con route type-safe e transizioni dichiarative.
  • Modifier è una catena di chiamate per personalizzare l'aspetto e il comportamento delle viste senza ereditarietà di classi.

Cos'è SwiftUI?

SwiftUI è un framework dichiarativo presentato da Apple nel 2019 per sostituire UIKit nei nuovi progetti. Invece di creare manualmente istanze UIView e aggiungerle alla gerarchia, lo sviluppatore descrive l'interfaccia attraverso strutture che conformano al protocollo View. SwiftUI calcola automaticamente la differenza tra lo stato corrente e quello nuovo e ridisegna solo le parti modificate utilizzando il proprio motore di rendering.

Il framework è scritto in Swift utilizzando value semantics (strutture, non classi), rendendo i componenti UI leggeri e thread-safe. A differenza di UIKit, dove UIViewController può pesare 200+ byte a causa del runtime Objective-C, una SwiftUI View è semplicemente una struttura di pochi byte. Questo è particolarmente importante per watchOS con la sua memoria limitata.

Multi-piattaforma SwiftUI

La stessa descrizione View funziona su iPhone, iPad, Mac, Apple Watch, Apple TV e Apple Vision Pro. SwiftUI adatta l'interfaccia alla piattaforma: gesti tattili su iOS, combinazioni di tastiera su macOS, scrolling Digital Crown su watchOS. Questo riduce i tempi di sviluppo per le aziende che rilasciano app su più piattaforme Apple, ma richiede configurazione aggiuntiva per elementi specifici di ogni piattaforma.

View Protocol e il corpo della vista

In SwiftUI, ogni schermata è una struttura che implementa il protocollo View con un unico requisito: una proprietà calcolata body di tipo some View. La parola chiave some (tipo opaco) nasconde il tipo concreto della vista, permettendo a SwiftUI di ottimizzare il rendering. All'interno di body, lo sviluppatore combina componenti pronti — Text, Image, Button, List — usando ViewBuilder, che assembla più viste in una sola.

swift
struct GreetingView: View {
    let name: String

    var var body: some View {
        VStack {
            Text("Ciao, \(name)!")
                .font(.title)
                .foregroundColor(.blue)
            Image(systemName: "hand.wave")
                .imageScale(.large)
        }
        .padding()
    }
}

Nell'esempio, VStack (stack verticale) contiene Text e Image. Il valore di name viene passato tramite l'inizializzatore della struttura — così funziona DI (Dependency Injection) in SwiftUI senza contenitori DI esterni. Ogni modificatore restituisce una nuova vista con la modifica applicata, senza mutare l'originale. Questo è possibile grazie all'immutabilità dei value types.

ViewBuilder e condizionali

ViewBuilder è un result builder annotato con @resultBuilder che assembla fino a 10 viste in una. All'interno di body si possono usare if/else, switch e ForEach senza wrapper aggiuntivi. ForEach lavora con elementi Identifiable — a ogni vista viene assegnato un id univoco per un'animazione corretta durante inserimento/rimozione.

Gestione dello stato: @State, @Binding, @ObservedObject

In SwiftUI, lo stato determina quale contenuto viene visualizzato sullo schermo. Quando lo stato cambia, SwiftUI ricrea il body della vista dipendente e confronta il risultato con il precedente usando un algoritmo di diff. Per memorizzare lo stato si usano property wrappers — ognuno risolve il suo compito specifico: stato locale, connessione con una vista figlia o modello dati esterno.

swift
struct CounterView: View {
    @State private var count = 0

    var var body: some View {
        VStack {
            Text("Contatore: \(count)")
            Button("Incrementa") {
                count += 1
            }
        }
    }
}

class UserViewModel: ObservableObject {
    @Published var name = ""
    @Published var age = 0
}

@State memorizza un valore locale semplice (Int, String, Bool) all'interno della struttura View. SwiftUI sposta la memoria dalla struttura a un archivio separato — quindi una proprietà con @State può essere mutata anche se View è un value type. @ObservableObject è per classi con proprietà @Published, i cui cambiamenti notificano automaticamente SwiftUI della necessità di ridisegnare.

@Binding e connessione genitore-figlio

@Binding crea una connessione bidirezionale con una fonte dati situata nella vista genitore. Il genitore passa $variable (projected value) e il figlio legge e scrive il valore attraverso il binding. Questo permette di spostare l'input di testo o un interruttore in un componente separato mantenendo lo stato nel genitore. Senza @Binding, ogni cambiamento richiederebbe una closure di callback per passare il nuovo valore verso l'alto.

Prima di iOS 16, la navigazione in SwiftUI era costruita su NavigationView — un'API legacy con comportamento complesso su iPad (split view, doppia colonna). A partire da iOS 16, Apple raccomanda NavigationStack — un'alternativa semplificata con route type-safe. Lo sviluppatore definisce un enum delle route possibili e NavigationStack gestisce automaticamente lo stack di schermate con supporto per deep link e ritorno alla radice.

swift
enum Route: Hashable {
    case detail(id: Int)
    case settings
}

struct ContentView: View {
    var var body: some View {
        NavigationStack {
            List {
                NavigationLink("Schermata dettaglio",
                               value: Route.detail(id: 42))
                NavigationLink("Impostazioni",
                               value: Route.settings)
            }
            .navigationDestination(for: Route.self) { route in
                switch route {
                case .detail(let id): DetailView(id: id)
                case .settings: SettingsView()
                }
            }
        }
    }
}

Le route conformi a Hashable permettono di usare qualsiasi tipo di dato per passare parametri. navigationDestination(for:destination:) associa il tipo di route alla vista di destinazione. Il vantaggio rispetto alla navigazione UIKit è che non è richiesto ridisegno quando si aggiunge una nuova route: basta aggiungere un case all'enum e un handler nello switch. I deep link vengono gestiti tramite processDeepLink su NavigationStack.

Navigazione programmatica

Per la navigazione programmatica (dopo login, timer o risposta del server), si usa @State con l'inizializzatore NavigationLink: NavigationLink(isActive: $isActive). Quando isActive = true, la transizione avviene senza tocco dell'utente. Un'alternativa è il binding dell'array $path in NavigationStack: $path.append(Route.detail(id: 1)).

View Modifier — personalizzazione dell'aspetto

Modifier è un metodo che restituisce una copia modificata della vista. A differenza di UIKit, dove la configurazione delle proprietà avviene mutando una vista esistente, SwiftUI crea un nuovo valore con la modifica applicata. L'incatenamento dei modificatori costruisce l'interfaccia finale da trasformazioni sequenziali: font → padding → colore → ombra → gesto.

Apple fornisce oltre 200 modificatori integrati. I più comuni: .font(), .foregroundColor(), .padding(), .background(), .cornerRadius(), .shadow(), .opacity(), .offset(). L'ordine dei modificatori è importante: .padding() prima di .background() riempie l'area con il padding, dopo — solo l'area interna. Modificatori personalizzati vengono creati tramite il protocollo ViewModifier.

Modificatori condizionali e animazione

I modificatori possono essere applicati condizionalmente tramite l'operatore ternario: .foregroundColor(isError ? .red : .primary). Per l'animazione si usa .animation(.easeInOut, value: state) — il modificatore di animazione è legato a una proprietà di stato specifica. Quando questa proprietà cambia, SwiftUI anima la transizione tra il vecchio e il nuovo valore. L'animazione funziona con opacity, offset, scale, rotation, dimensione e colore — ogni proprietà ha un corrispondente AnimatableParameter.

Per animazioni personalizzate, sono disponibili .transition (comparsa/scomparsa) e .matchedGeometryEffect (transizione fluida di un elemento tra due contenitori). Quest'ultimo viene usato per le hero animation nelle liste: un'icona in una cella della lista si trasforma dolcemente in un'immagine grande nella schermata di dettaglio.

SwiftUI vs UIKit: confronto degli approcci

La scelta tra SwiftUI e UIKit è uno dei primi dilemmi dello sviluppatore iOS. Entrambi i framework sono supportati da Apple ma risolvono il problema della costruzione dell'interfaccia in modi fondamentalmente diversi: SwiftUI dichiarativamente, UIKit imperativamente. La differenza si manifesta nella gestione dello stato, navigazione, prestazioni e compatibilità.

AspettoSwiftUIUIKit
ApproccioDichiarativo: cosa mostrareImperativo: come costruire
StatoProperty Wrappers, ridisegno automaticoManuale: reloadData, setNeedsLayout
Codice UICompatto, catene di modificatoriVerboso, NSCoder/Storyboard/vincoli
PrestazioniAlte su iOS 17+, algoritmo diffPicco su iOS 12–16, controllo diretto
Versione minimaiOS 15+ (supporto completo)iOS 2+ (tutte le versioni)

Per i nuovi progetti con versione minima iOS 17, Apple raccomanda SwiftUI come framework principale. UIKit rimane necessario per interfacce che richiedono controllo fine sul rendering (UICollectionViewLayout personalizzato, scene CAAnimation complesse) o supporto per iOS 12–14. Molti progetti usano un approccio ibrido: SwiftUI tramite UIHostingController viene incorporato in un'app UIKit, e UIViewRepresentable permette di usare componenti UIKit all'interno della gerarchia SwiftUI.

Domande frequenti

Si possono usare SwiftUI e UIKit nello stesso progetto?

Sì, tramite UIHostingController (SwiftUI in UIKit) e UIViewRepresentable (UIKit in SwiftUI). È un approccio ibrido, popolare durante la migrazione.

Con quale versione di iOS iniziare un progetto SwiftUI?

iOS 17 offre funzionalità complete: NavigationStack, Observation framework, Swift Charts. iOS 15 è la soglia minima per la produzione.

Perché SwiftUI a volte non aggiorna l'interfaccia?

La causa più frequente è la modifica di una proprietà @Published su un thread secondario. ObservableObject deve inviare le modifiche sul main actor: @MainActor class ViewModel.

Come gestire il debounce alla pressione di un pulsante in SwiftUI?

Usa .debounce tramite Combine: Button.publisher(for: .tap) .debounce(for: .seconds(0.3), scheduler: RunLoop.main).

SwiftUI supporta gesti personalizzati?

Sì, tramite i modificatori Gesture: DragGesture, LongPressGesture, MagnificationGesture, RotationGesture. Combinali con .simultaneousGesture() e .sequenced().

Riepilogo

  • SwiftUI è un framework dichiarativo di Apple dove l'interfaccia è descritta come una composizione di strutture View con property wrappers per la gestione dello stato.
  • View Protocol con la proprietà calcolata body è il punto di ingresso unico per qualsiasi vista. ViewBuilder assembla fino a 10 viste in una senza contenitori extra.
  • @State, @Binding e @ObservedObject coprono tutti gli scenari di gestione dei dati: stato locale, connessione genitore-figlio e modelli esterni.
  • NavigationStack con route enum type-safe ha sostituito NavigationView, aggiungendo supporto per deep link e navigazione programmatica.
  • Modifier è un pattern chiave di SwiftUI che permette di personalizzare l'aspetto delle viste tramite una catena di chiamate senza ereditarietà.
  • SwiftUI e UIKit coesistono tramite UIHostingController e UIViewRepresentable, permettendo una migrazione graduale del progetto.
  • Per iOS 17+, Apple raccomanda SwiftUI come framework principale; UIKit rimane per interfacce personalizzate complesse e supporto di versioni precedenti.

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