Cos'è Swift e a cosa serve davvero
Cos'è Swift: gli optional spiegati sul serio, struct contro class, SwiftUI o UIKit, il vincolo del Mac e gli errori che fanno perdere ore a chi inizia.
Hai deciso che vuoi fare app per iPhone, hai aperto il primo tutorial di Swift e nella terza riga c'è un punto interrogativo attaccato a un tipo che nessuno ti spiega. Poi arriva un punto esclamativo, poi if let, e a quel punto smetti di capire. In questo articolo ti spiego cosa sono davvero quei simboli, perché sono la parte migliore del linguaggio, e qual è il vincolo concreto che nessuno dice all'inizio.
Cos'è Swift
Swift è un linguaggio compilato creato da Apple nel 2014 per sostituire Objective-C nello sviluppo di app per i suoi sistemi, progettato attorno all'idea che il compilatore debba impedire in partenza gli errori che negli anni facevano crashare le app in produzione.
Il contesto conta. Prima di Swift si scrivevano app iPhone in Objective-C, un linguaggio degli anni Ottanta con una sintassi che spaventava chiunque arrivasse da altrove. Apple non aveva bisogno di un linguaggio più veloce: aveva bisogno di uno che la gente fosse disposta a imparare, e che rendesse impossibile un'intera categoria di crash.
Swift è open source dal 2015: gira su Linux, ci si scrivono server e strumenti a riga di comando. La frase "Swift serve solo per iOS" è quindi tecnicamente falsa — ma è anche vero, e lo vedremo, che fuori dall'ecosistema Apple l'adozione reale resta limitata.
Gli optional: il concetto che spaventa e che risolve tutto
Il problema che gli optional risolvono è vecchio quanto la programmazione: una variabile che dovrebbe contenere un valore e invece è vuota. In Java è il NullPointerException, in C# la NullReferenceException, in JavaScript è undefined is not a function. È, storicamente, la prima causa di crash delle applicazioni.
Swift lo affronta nel sistema dei tipi. Una variabile normale non può mai essere vuota:
var nome: String = "Edoardo"
nome = nil // errore di compilazione: non compila proprio
Se un valore può mancare, lo dichiari esplicitamente con il ?:
var soprannome: String? = nil // va benissimo
String? e String sono due tipi diversi. Il primo è una scatola che può essere piena o vuota, e prima di usare quello che c'è dentro devi aprirla. Questa è tutta la storia: il punto interrogativo non è un dettaglio di sintassi, è una promessa che il compilatore ti obbliga a mantenere.
Come si apre la scatola
Il modo idiomatico è if let o guard let:
func saluta(_ soprannome: String?) {
guard let s = soprannome else {
print("Ciao, sconosciuto")
return
}
print("Ciao \(s)") // qui s è una String normale, garantita
}
guard let è la forma che vedrai più spesso nel codice serio: gestisce subito il caso vuoto e esce, così il resto della funzione lavora con dati certi. È il contrario delle piramidi di if annidati.
Ci sono due scorciatoie che userai spesso:
let lunghezza = soprannome?.count // optional chaining: risultato Int?
let mostrato = soprannome ?? "anonimo" // valore di riserva se è nil
Il ?. significa "se c'è qualcosa, chiama il metodo; altrimenti restituisci nil senza esplodere". Il ?? fornisce un valore alternativo. Insieme coprono gran parte dei casi reali.
E il punto esclamativo
Il ! è il force unwrap: "apri la scatola e fidati che dentro ci sia qualcosa". Se è vuota, l'app si chiude all'istante.
let s = soprannome! // se soprannome è nil, crash immediato
Serve in quei pochi casi dove sai per certezza strutturale che il valore esiste. Nella pratica di chi inizia è la scorciatoia usata per far tacere il compilatore, ed è il modo più rapido per riportare in Swift esattamente i crash che Swift era nato per eliminare.
Struct o class: la scelta che distingue Swift
Chi arriva da Java o C# dà per scontato che un oggetto sia un oggetto. In Swift ci sono due categorie diverse e la differenza è concreta.
Le struct sono value type: si copiano. Quando le assegni o le passi a una funzione, ne nasce una copia indipendente.
struct Punto { var x: Int; var y: Int }
var a = Punto(x: 0, y: 0)
var b = a
b.x = 10
print(a.x) // 0 — a non è stato toccato
Le class sono reference type: si condividono. Due variabili puntano alla stessa istanza.
class Contatore { var valore = 0 }
let c1 = Contatore()
let c2 = c1
c2.valore = 5
print(c1.valore) // 5 — è lo stesso oggetto
struct | class | |
|---|---|---|
| Semantica | Copia | Riferimento |
| Ereditarietà | No | Sì |
| Conteggio riferimenti | Non serve | Sì, con rischio di cicli |
| Uso tipico | Dati, modelli, stato | Oggetti con identità e ciclo di vita |
La convenzione nella comunità Swift è partire da struct e passare a class solo quando ti serve ereditarietà, identità dell'oggetto o interoperabilità con framework che la richiedono. Il motivo è che il codice basato su copie è molto più facile da ragionare: nessuno può modificarti un dato alle spalle da un'altra parte del programma.
È una filosofia diversa da quella dei linguaggi a oggetti classici, e se vieni da lì è il punto che richiede più riprogrammazione mentale — più degli optional.
SwiftUI o UIKit: cosa scegliere oggi
Sono i due modi di costruire l'interfaccia, e la domanda torna in ogni discussione.
UIKit è il framework storico, imperativo: crei le viste, le configuri, le aggiorni a mano quando i dati cambiano. È maturo, prevedibile, documentato da oltre un decennio di articoli e risposte online.
SwiftUI è dichiarativo: descrivi come deve apparire l'interfaccia in funzione dello stato, e il framework si occupa di aggiornarla.
struct ContatoreView: View {
@State private var conteggio = 0
var body: some View {
VStack {
Text("Hai premuto \(conteggio) volte")
Button("Premi") { conteggio += 1 }
}
}
}
Se conosci React, il modello ti è familiare: stato, vista derivata dallo stato, nessun aggiornamento manuale.
Cosa scegliere, onestamente: per un progetto nuovo si parte da SwiftUI, è la direzione dichiarata di Apple e si scrive molto meno codice. Ma UIKit non è morto e non lo sarà a breve, per tre ragioni concrete:
- Gran parte delle app in produzione è scritta in UIKit, e nessuno riscrive centomila righe per moda. Se entri in un'azienda, molto probabilmente lo troverai.
- Alcune personalizzazioni fini dell'interfaccia in SwiftUI o non si fanno o si fanno incapsulando un componente UIKit.
- Le funzionalità nuove di SwiftUI richiedono versioni recenti di iOS. Se il progetto supporta sistemi più vecchi, il tuo raggio d'azione si restringe.
La posizione ragionevole: impara SwiftUI per primo, ma non stupirti se il lavoro vero ti chiede di conoscere anche UIKit.
Il vincolo vero: ti serve un Mac
Questo va detto prima, non alla fine, perché è l'unico ostacolo che non si aggira con la buona volontà.
Per sviluppare app iOS in modo serio ti serve Xcode, che gira solo su macOS. Xcode contiene il compilatore, il simulatore di iPhone, gli strumenti di profilazione e la procedura di firma e pubblicazione sull'App Store. Non esiste una versione per Windows o Linux, e le soluzioni alternative — macchine virtuali di dubbia legalità, Mac in affitto nel cloud, servizi di build remota — funzionano a singhiozzo e non sono un modo sensato di imparare.
A questo si aggiunge l'account sviluppatore Apple, che ha un costo annuale per pubblicare sullo store (la cifra la verifichi alla fonte, cambia nel tempo e per area).
Quindi: il costo d'ingresso è reale ed è hardware. Se non hai un Mac e non hai intenzione di comprarne uno, prima di investire mesi su Swift confronta le alternative multipiattaforma — il quadro è in scegliere la tecnologia per un'app mobile e in React Native o Flutter. Va detto per completezza che anche per compilare la versione iOS di un'app Flutter o React Native serve comunque un Mac: il vincolo si sposta, non sparisce.
Swift fuori da iOS
Dato che è open source, Swift gira su Linux e ci si scrivono cose:
- Server-side, con framework come Vapor. Tecnicamente funziona bene: tipizzazione forte, prestazioni buone, concorrenza moderna con
async/awaite gli attori. - Strumenti a riga di comando, compilati in binario nativo.
- App per macOS, watchOS, tvOS e visionOS, che restano comunque dentro l'ecosistema Apple.
Il limite è l'adozione. Un backend in Swift è una scelta minoritaria: trovare librerie mature, esempi e persone che lo conoscano è più difficile che con Go, Java o Node.js. Se il team è già fatto di sviluppatori iOS ha un senso; altrimenti stai scegliendo la strada in salita per motivi estetici.
Errori comuni che fanno perdere ore
Usare ! per far tacere il compilatore. È l'errore numero uno. Il compilatore ti sta segnalando che quel valore può essere vuoto; mettere un punto esclamativo non lo rende pieno, sposta solo il crash da compilazione a runtime — cioè sul telefono dell'utente. Usa guard let, if let o ??.
Retain cycle con le closure. Le class in Swift si liberano tramite conteggio dei riferimenti. Se una closure cattura self e l'oggetto tiene la closure, nessuno dei due arriva mai a zero e la memoria non viene liberata. La forma corretta:
caricaDati { [weak self] risultato in
guard let self else { return }
self.aggiorna(risultato)
}
[weak self] dice "tienilo, ma senza contare come riferimento". È una di quelle cose che non capisci finché non profilate l'app e vedete la memoria salire a ogni apertura di schermata.
Confondere struct e class. Modifichi una copia e ti chiedi perché l'originale non cambia, oppure usi una class per un semplice modello di dati e ti ritrovi mutazioni impreviste da tre punti diversi del codice. Chiediti sempre: questo valore ha un'identità, o è solo un dato?
Bloccare il thread principale. Tutta l'interfaccia vive lì. Una chiamata di rete o un'elaborazione pesante eseguita sul main thread congela l'app. Swift moderno risolve con async/await, ma va usato.
Fare force unwrap degli optional che arrivano dal JSON. I dati che arrivano dalla rete sono la fonte meno affidabile che esista. Se il server cambia un campo, l'app si chiude. È esattamente il caso in cui gli optional esistono.
In sintesi
Swift è il linguaggio dell'ecosistema Apple, ed è lì che ha senso impararlo: iOS, macOS, watchOS, visionOS. È open source e gira su Linux, ma fuori dai dispositivi Apple l'adozione reale resta di nicchia, e sceglierlo per un backend è una decisione da giustificare.
Gli optional sono la caratteristica che vale il prezzo del biglietto. Quel punto interrogativo che all'inizio irrita è il sistema dei tipi che ti costringe a gestire il caso "valore assente" prima che diventi un crash sul telefono di qualcun altro. Il momento in cui smetti di combatterli è il momento in cui inizi a scrivere Swift.
La distinzione struct/class è il concetto che richiede più riprogrammazione se vieni da Java o C#. Parti da struct, passa a class quando ti serve identità o ereditarietà, e ricordati che le classi portano con sé il problema dei cicli di riferimento.
Il vincolo del Mac è reale e non negoziabile. È un costo d'ingresso hardware, va messo nel conto prima di iniziare, e vale anche se poi scegli una tecnologia multipiattaforma. Se il punto è capire quanto rende quel percorso, la lettura è quanto guadagna un mobile developer in Italia; per collocare Swift rispetto a tutto il resto c'è tutti i linguaggi di programmazione.
Se vuoi partire con un percorso guidato invece che a tentativi, dai un'occhiata ai corsi.