Swift è un linguaggio di programmazione moderno di Apple, presentato al WWDC 2014 come sostituto di Objective-C. Swift combina tipizzazione sicura, gestione automatica della memoria ARC (Automatic Reference Counting) e un approccio orientato ai protocolli. Swift Programming Language è la fonte principale per la sintassi e la libreria standard del linguaggio.
Punti chiave
Swift è un linguaggio di programmazione multiparadigma sviluppato da Apple per iOS, macOS, watchOS, tvOS e visionOS. Gli obiettivi chiave del linguaggio sono: sicurezza, velocità ed espressività sintattica. Swift utilizza il compilatore LLVM e genera codice macchina ottimizzato, con prestazioni paragonabili al C++.
Dal suo rilascio nel 2014, Swift ha attraversato 6 versioni principali. Swift 6 (2024) ha introdotto un modello completo di sicurezza contro le race condition attraverso uno stretto controllo dell'isolamento del codice concorrente. Secondo GitHub Octoverse 2025, Swift rientra tra le prime 10 lingue per crescita della comunità, superando Rust e Kotlin in velocità di adozione sulle piattaforme Apple.
Swift è open source e multipiattaforma — il codice sorgente è pubblicato su GitHub (Swift Open Source). Oltre alle piattaforme Apple, Swift viene utilizzato su Linux e Windows per lo sviluppo lato server (Vapor, Hummingbird), sebbene il suo dominio principale rimanga lo sviluppo mobile e desktop nell'ecosistema Apple.
Le principali ragioni della transizione: Swift elimina intere classi di errori possibili in Objective-C. La sicurezza dei tipi previene le discrepanze di tipo in fase di compilazione. Gli Optionals eliminano i dereferenziamenti nil. ARC è integrato dal primo giorno, a differenza di MRC/ARC in Objective-C. La sintassi di Swift è più breve e leggibile — gli studi mostrano una riduzione del 30-40% del volume di codice rispetto a Objective-C per attività equivalenti.
La sintassi di base di Swift combina costruzioni familiari simili a C con elementi di linguaggi funzionali. Le variabili vengono dichiarate con var, le costanti con let. Il compilatore utilizza l'inferenza di tipo, quindi l'annotazione esplicita del tipo è necessaria solo in caso di ambiguità.
import Foundation
// Costanti e variabili
let name = "Swift"
var version = 6.0
var count: Int = 42
// Funzioni con parametri predefiniti
func greet(person: String, greeting: String = "Hello") -> String {
return "\(greeting), \(person)!"
}
// Guard-let per uscita anticipata
func parse(input: String?) -> Int {
guard let value = input, let number = Int(value) else {
return 0
}
return number
}Switch e pattern matching in Swift sono più potenti che in C e Kotlin. Switch supporta la corrispondenza con tuple, intervalli, condizioni where e binding di valori. Il compilatore verifica la copertura esaustiva di tutti i casi — l'assenza di default non è un errore se tutti i valori possibili sono coperti.
let point = (x: 3, y: -1)
switch point {
case (0, 0):
print("Origine")
case let (x, y) where x == y:
print("X è uguale a Y")
case let (x, y) where abs(y) > x:
print("Il valore assoluto di Y è maggiore di X")
default:
print("Punto (\(point.x), \(point.y))"point.x), \(point.y))")
}Gli Optionals sono un concetto centrale di Swift che risolve il problema dei riferimenti nulli a livello del sistema di tipi. Optional
var optionalString: String? = "Hello"
optionalString = nil // consentito
// Optional Binding — estrazione sicura
if let text = optionalString {
print("Testo: \(text)"text)")
} else {
print("Valore assente")
}
// Optional Chaining — accesso sicuro alle proprietà
let length = optionalString?.count ?? 0
// Operatore nil-coalescing
let greeting = optionalString ?? "Default"Optional Chaining con l'operatore ?. consente di chiamare metodi e accedere alle proprietà di un valore opzionale in modo sicuro. Se la catena viene interrotta da nil, il risultato dell'intera espressione è nil. Nil-coalescing (??) fornisce un valore predefinito ed è ampiamente utilizzato nel codice UI per visualizzare testo segnaposto.
I protocolli in Swift definiscono un contratto — un insieme di proprietà e metodi. A differenza delle interfacce Java, i protocolli Swift possono avere implementazioni predefinite tramite le estensioni di protocollo (protocol extensions). Questa è la base della Programmazione Orientata ai Protocolli, l'approccio raccomandato da Apple invece dell'ereditarietà di classi.
protocol NamedEntity {
var name: String { get }
func description() -> String
}
// Implementazione predefinita tramite extension
extension NamedEntity {
func description() -> String {
return "Entity: \(name)"
}
}
// Conformità tramite extension
extension String: NamedEntity {
var name: String { return self }
}Le estensioni di protocollo consentono di aggiungere metodi a un protocollo senza modificare ogni tipo conforme. Questo è particolarmente utile per aggiungere utilità comuni: map, filter, reduce per Sequence, o Codable per la serializzazione JSON. Apple ha costruito molti framework (SwiftUI, Combine) su protocolli con estensioni.
Le closure in Swift sono funzioni anonime che catturano variabili dal contesto esterno. Sintatticamente, le closure assomigliano alle lambda in Kotlin ma con una sintassi più flessibile: trailing closure, nomi di argomento abbreviati ($0, $1) e autoclosures.
// Closure con cattura del contesto
let numbers = [5, 3, 8, 1, 9]
// Trailing closure syntax
let sorted = numbers.sorted { $0 < $1 }
// Catena funzionale
let result = numbers
.filter { $0 > 3 }
.map { $0 * 2 }
.reduce(0, +)
// Closure come parametro di funzione
func performAsync(completion: @escaping (Result<Data, Error>) -> Void) { }Le closure @escaping vengono utilizzate quando la closure viene eseguita dopo il ritorno della funzione — tipicamente per richieste di rete e operazioni asincrone. @autoclosure incapsula automaticamente un'espressione in una closure, utilizzata in assert e logica di cortocircuito.
La scelta tra struct e class è una delle prime decisioni quando si progetta un modello Swift. Apple raccomanda di utilizzare struct per impostazione predefinita (tipo valore) e passare a class (tipo riferimento) solo quando è necessaria l'ereditarietà o l'identità di riferimento.
| Caratteristica | Struct | Class |
|---|---|---|
| Tipo di passaggio | Per valore (copia) | Per riferimento |
| Ereditarietà | Non supportata | Supportata |
| Gestione ARC | Non richiesta | ARC (conteggio riferimenti) |
| Deinizializzatore deinit | No | Sì |
| Mutabilità | mutating func per modificare le proprietà | Qualsiasi metodo può modificare |
| Archiviazione in collezioni | Copiato all'inserimento | Riferimento archiviato |
I tipi valore (struct) sono più sicuri in ambienti multithread — ogni thread ottiene una copia indipendente. I tipi riferimento (class) sono necessari per lavorare con UIKit (UIView, UIViewController), dove sono richiesti identità di riferimento ed ereditarietà dalle classi di sistema.
ARC (Automatic Reference Counting) è il sistema di gestione della memoria di Swift per i tipi riferimento. Il compilatore inserisce chiamate retain/release in fase di esecuzione, tracciando il numero di riferimenti forti a un oggetto. Quando il contatore raggiunge zero, l'oggetto viene immediatamente rilasciato.
Il problema principale di ARC sono i cicli di ritenzione (retain cycles). Quando due oggetti mantengono riferimenti forti l'uno verso l'altro, la memoria non viene mai liberata. La soluzione sono i riferimenti deboli (weak, diventano automaticamente nil al rilascio) e i riferimenti unowned (garantiscono che l'oggetto sia vivo).
class ProfileViewController: UIViewController {
var onLogout: (() -> Void)?
func setupHandler() {
// [weak self] previene il retain cycle
onLogout = { [weak self] in
guard let self else { return }
self.dismiss(animated: true)
}
}
}Per prevenire i retain cycle nelle closure, utilizzare [weak self] con guard let self = self else { return }. Questa regola è particolarmente importante in UIKit, dove il ViewController mantiene riferimenti forti alle sue proprietà e le closure all'interno di tali proprietà riferiscono al ViewController.
Domande frequenti
Swift supporta Int, Double, Float, String, Bool, Array, Set, Dictionary e tuple. I tipi numerici hanno dimensione fissa: Int8, Int16, Int32, Int64 e UInt senza segno. Per lavorare con le date si usa Date di Foundation; per i dati — Data.
Optional è un enum con due casi: .none (nil) e .some(Wrapped). Swift richiede la verifica esplicita di Optional tramite if let, guard let o ??, eliminando NullPointerException. Le catene opzionali (?.) consentono di accedere in modo sicuro alle proprietà di valori opzionali annidati.
Struct — tipo valore, copiato nell'assegnazione, non supporta l'ereditarietà, non richiede ARC. Class — tipo riferimento, passato per riferimento, supporta l'ereditarietà e i deinizializzatori. Apple raccomanda struct come tipo predefinito.
ARC conta automaticamente i riferimenti forti agli oggetti delle classi. Quando il contatore raggiunge zero, la memoria viene liberata. Per prevenire i cicli di ritenzione, utilizzare weak (nil automatico) e unowned (durata di vita garantita). ARC non si applica a struct ed enum.
La Programmazione Orientata ai Protocolli è un approccio che utilizza protocolli con estensioni invece di gerarchie di classi. I protocolli possono contenere implementazioni predefinite di metodi tramite le estensioni di protocollo. Ciò consente il riutilizzo del codice senza ereditarietà, mantenendo flessibilità e testabilità.
Riepilogo
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.
Leggi anche