iOS Deployment Target (anche iOS Target, Deployment Target) è la versione minima del sistema operativo Apple su cui un'applicazione può essere eseguita. Questo parametro viene impostato nel progetto Xcode e definisce il limite di compatibilità: selezionando iOS 16.0, l'applicazione viene installata solo su dispositivi con iOS 16.0 o successivo. Secondo Apple Developer Documentation, la scelta del giusto Deployment Target influenza sia la portata del pubblico che l'accesso alle nuove API dei framework Swift e Objective-C.
Punti Chiave
iOS Deployment Target è un parametro di configurazione di Xcode che specifica la versione più vecchia di iOS, iPadOS, tvOS, watchOS o visionOS su cui un'applicazione può essere eseguita. Ogni progetto Xcode contiene questa impostazione separatamente per ogni piattaforma. Ad esempio, un'app iOS può avere Deployment Target 16.0, mentre un'estensione watchOS — 9.0. Se il dispositivo dell'utente esegue iOS 15.0, un'app con Target 16.0 non apparirà nell'App Store e non potrà essere installata tramite distribuzione diretta.
Il meccanismo del Deployment Target si basa sul controllo della versione del SO durante l'installazione. L'App Store di iOS confronta il valore del Deployment Target da Info.plist (chiave MinimumOSVersion) con la versione del SO sul dispositivo dell'utente. Se la versione del dispositivo è inferiore — il pulsante "Scarica" viene bloccato e l'API dell'App Store non restituisce l'applicazione nei risultati di ricerca per quel dispositivo. Lo stesso comportamento si applica a TestFlight, distribuzione ad-hoc ed enterprise.
Secondo i dati StatCounter di giugno 2025, iOS 16 rappresenta circa il 48% dei dispositivi iPhone attivi, iOS 17 — 35%, iOS 18 — 12%, versioni più vecchie — circa il 5%. Scegliere Deployment Target 16.0 copre l'83% dei dispositivi, Target 17.0 — 35% (solo iOS 17+). Questi numeri sono critici per il processo decisionale: più alto è il Target, più piccola è l'audience, ma più accessibili sono le più recenti API SwiftUI e UIKit.
| Deployment Target | Quota dispositivi (giugno 2025) | Funzionalità disponibili |
|---|---|---|
| iOS 15.0 | ~90% | Swift Concurrency, async/await, Focus State |
| iOS 16.0 | ~83% | SwiftUI NavigationStack, Layout, Live Activities |
| iOS 17.0 | ~35% | Observation, SwiftData, TipKit, Reactive Editing |
| iOS 18.0 | ~12% | Nuove API Apple Intelligence, SwiftUI migliorato |
Ogni nuova versione di iOS aggiunge non solo funzionalità per l'utente, ma anche API per gli sviluppatori. Nuovi modificatori SwiftUI, metodi UIKit, framework come SwiftData e Observation sono disponibili solo con un Deployment Target specifico. Lo sviluppatore deve bilanciare tra portata del pubblico e disponibilità di strumenti moderni.
iOS Deployment Target e minSdkVersion di Android svolgono la stessa funzione — impostano la versione minima del SO per un'applicazione. Tuttavia, i meccanismi di implementazione e gli strumenti associati differiscono. Comprendere queste differenze è utile per gli sviluppatori che lavorano su entrambe le piattaforme e aiuta a evitare confusione quando si passa da un ecosistema all'altro.
In iOS, la versione minima viene impostata tramite le impostazioni di build di Xcode (IPHONEOS_DEPLOYMENT_TARGET) e memorizzata in Info.plist (MinimumOSVersion). In Android — tramite build.gradle (minSdkVersion) e AndroidManifest.xml (<uses-sdk android:minSdkVersion>). iOS non ha equivalenti per targetSdkVersion e compileSdkVersion — i cambiamenti comportamentali in iOS sono gestiti dall'SDK con cui l'applicazione è stata compilata (Base SDK) e dalla versione del SO sul dispositivo.
| Parametro | iOS | Android |
|---|---|---|
| Versione minima | Deployment Target (IPHONEOS_DEPLOYMENT_TARGET) | minSdkVersion |
| Dove specificato | Xcode Build Settings → Info.plist | build.gradle → AndroidManifest.xml |
| Controllo nel codice | @available / #available / if #available | Build.VERSION.SDK_INT |
| Versione target | Base SDK (sempre l'ultima) | compileSdkVersion + targetSdkVersion |
| Filtraggio nello store | App Store: MinimumOSVersion | Google Play: minSdkVersion |
La differenza principale è che Base SDK in iOS è sempre l'ultima versione installata in Xcode. Lo sviluppatore non può scegliere compileSdkVersion come in Android — l'applicazione viene sempre compilata contro l'ultimo SDK disponibile. I nuovi cambiamenti comportamentali in iOS si applicano a tutte le applicazioni compilate con il nuovo Base SDK, indipendentemente dal Deployment Target. In Android, targetSdkVersion fornisce controllo sui cambiamenti comportamentali; iOS non ha questa separazione.
A differenza di Android, dove i cambiamenti comportamentali sono legati a targetSdkVersion, iOS applica cambiamenti comportamentali a tutte le applicazioni compilate con la nuova versione di Xcode e Base SDK. Ad esempio, iOS 13 ha introdotto la Modalità Scura — tutte le applicazioni compilate con Xcode 11 e iOS 13 SDK hanno ricevuto automaticamente il supporto per il tema scuro, indipendentemente dal Deployment Target. In Android, un cambiamento simile (Scoped Storage) si applica solo quando targetSdk >= 29. Gli sviluppatori iOS devono essere preparati ai cambiamenti comportamentali con ogni nuovo Xcode, senza possibilità di rinvio.
La conoscenza di entrambe le piattaforme consente di prevedere le conseguenze della scelta di una versione minima e pianificare gli aggiornamenti del codice per le nuove API. In IT Sectr, utilizziamo entrambi gli ecosistemi dal 2017 — la pratica mostra che l'iOS Deployment Target dovrebbe essere scelto 2-3 versioni sotto quella corrente per un equilibrio tra copertura e funzionalità.
La configurazione dell'iOS Deployment Target viene eseguita in diversi punti del progetto: il Target principale, il progetto Pods (se si utilizza CocoaPods), le dipendenze di Swift Package Manager e i target Widget/Extension. Se i valori differiscono tra l'applicazione principale e le estensioni, l'App Store utilizza il massimo di tutti — cioè un'estensione non può avere un Target inferiore all'applicazione principale.
Aprire il progetto Xcode → selezionare il Target → scheda General → sezione Minimum iOS Deployment. L'elenco a discesa mostra tutte le versioni disponibili dell'SDK iOS installate in Xcode. La modifica si applica a tutti gli schemi di build. In alternativa — scheda Build Settings → iOS Deployment Target (IPHONEOS_DEPLOYMENT_TARGET). Se il progetto contiene più Target di estensione (Widget, Watch), ciascuno ha il proprio Deployment Target.
Per le librerie distribuite tramite SPM, il Deployment Target viene specificato in Package.swift nel parametro platforms. Una libreria con platforms: [.iOS(.v16)] sarà disponibile solo per applicazioni con Deployment Target iOS 16.0+. Aggiungendo tale libreria a un progetto con Target 15.0, Xcode mostrerà un errore di incompatibilità. In CocoaPods, il Deployment Target viene impostato nel Podfile: platform :ios, '16.0'.
// Package.swift — Deployment Target per libreria SPM
import PackageDescription
let package = Package(
name: "MyLibrary",
platforms: [
.iOS(.v16),
.macOS(.v13),
.watchOS(.v9),
.tvOS(.v16)
],
products: [
.library(
name: "MyLibrary",
targets: ["MyLibrary"]
)
],
dependencies: [],
targets: [
.target(
name: "MyLibrary",
swiftSettings: [
.enableUpcomingFeature("ConciseMagicFile")
]
)
]
)
// Verifica compatibilità nel codice
#if swift(>=5.9)
// Funzionalità Swift 5.9+ (Xcode 15+)
#endifNell'esempio, Package.swift imposta le piattaforme iOS 16+, macOS 13+, watchOS 9+, tvOS 16+. Qualsiasi progetto con Deployment Target inferiore a iOS 16.0 non potrà aggiungere questa libreria. Il parametro swiftSettings include le prossime funzionalità per una versione specifica di Swift. SPM verifica automaticamente la compatibilità delle platforms quando si aggiunge una dipendenza.
Il Podfile utilizza la direttiva platform :ios, '16.0'. Dopo pod install, CocoaPods verifica il Deployment Target di ogni libreria pod: se almeno una ha un Target superiore al progetto, l'installazione fallirà con l'errore "The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 17.0, but the range of supported deployment target versions is 16.0 to 17.0". La soluzione è ridurre il Target del pod problematico o aumentare il Target del progetto.
# Podfile — esempio con Deployment Target
platform :ios, '16.0'
# Ignora avvisi di Deployment Target
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.0'
end
end
endL'hook post_install nel Podfile imposta forzatamente il Deployment Target 16.0 per tutte le librerie pod. Ciò è utile quando uno dei pod specifica un Target più alto del necessario per la sua funzionalità. Utilizzatelo solo se siete sicuri che il pod non utilizzi API di una versione iOS superiore.
@available e #available sono direttive Swift e Objective-C per chiamare in modo sicuro API che sono disponibili solo su determinate versioni del SO. Se il Deployment Target del progetto è iOS 16.0 e un metodo richiede iOS 17.0, una chiamata diretta causerà un crash in fase di esecuzione su dispositivi con iOS 16.0–16.x. I controlli di disponibilità sono uno strumento obbligatorio per supportare più versioni di iOS.
La direttiva @available si applica a classi, metodi o file interi. Se @available(iOS 17.0, *) viene specificato prima di una classe, l'intera classe è disponibile solo su iOS 17.0+. Tentare di chiamare la classe su iOS 16.0 causerà un errore in fase di esecuzione. Utilizzare @available per isolare interi moduli di funzionalità specifici di una particolare versione del SO. Per i metodi all'interno di una classe, @available consente di nascondere funzioni individuali.
La direttiva #available (if #available) controlla la versione del SO in fase di esecuzione ed esegue il codice solo quando corrisponde. Viene utilizzata all'interno delle funzioni per scegliere tra implementazioni nuove e vecchie. In Objective-C, l'equivalente è @available(iOS 17.0, *) all'interno di if. Per controlli più complessi, utilizzare ProcessInfo.processInfo.isOperatingSystemAtLeast per confrontare i componenti della versione (major, minor, patch).
import UIKit
import SwiftUI
// 1. @available — intera classe solo per iOS 17+
@available(iOS 17.0, *)
class ObservationViewModel: ObservableObject {
@Published var name: String = "User"
// Usa Observation framework — disponibile solo iOS 17+
func updateWithObservation() {
let newName = "Updated via Observation"
name = newName
}
}
// 2. #available — chiamata condizionale all'interno di funzione
func configureLiveActivity() {
if #available(iOS 16.1, *) {
// API Live Activities — disponibile da iOS 16.1
let activity = Activity<MyAttributes>(
attributes: MyAttributes(name: "Live"),
contentState: MyContentState(value: 42)
)
Task {
await activity.activate()
}
} else {
// Fallback: notifica push o nulla
print("Live Activities non disponibile")
}
}
// 3. ProcessInfo — controllo preciso della versione
func checkOSVersion() {
let osVersion = ProcessInfo.processInfo.operatingSystemVersion
print("iOS \(osVersion.majorVersion).\(osVersion.minorVersion).\(osVersion.patchVersion)")
// Confronto componenti
if osVersion.majorVersion >= 17 {
print("iOS 17+ rilevato")
}
}
// 4. Objective-C @available
// Objective-C usa @available:
// if (@available(iOS 17.0, *)) { }
// 5. @available con argomento unavailable
@available(*, unavailable, message: "Use configureWithSwiftUI instead")
func legacyConfigureMethod() { }La classe ObservationViewModel utilizza @available per isolare le funzionalità di iOS 17. La funzione configureLiveActivity utilizza #available per verificare Live Activities (iOS 16.1+) con un'implementazione di fallback. ProcessInfo controlla la versione esatta del SO. @available(*, unavailable) contrassegna un metodo come non disponibile su tutte le versioni — per la migrazione a una nuova API. Senza questi controlli, un'applicazione con Deployment Target 16.0 si bloccherà su dispositivi con iOS 16.0 quando chiama API di iOS 17.
Objective-C utilizza @available(iOS 17.0, *) con la stessa semantica di Swift #available. La differenza: Objective-C controlla in fase di esecuzione, Swift #available è anch'esso in fase di esecuzione ma con suggerimenti del compilatore per l'ottimizzazione dei rami. Per il codice Objective-C che interagisce con Swift, i controlli di disponibilità sono necessari sul lato Objective-C — il bridging Swift non aggiunge controlli automatici.
Scegliere l'iOS Deployment Target è una decisione strategica che influenza tre aspetti: portata del pubblico, API disponibili e complessità di manutenzione del codice. Non esiste un valore corretto unico — la scelta dipende dal pubblico target dell'applicazione, dalle funzionalità minime richieste e dalle risorse del team per il supporto della retrocompatibilità.
Il primo fattore — statistiche di utilizzo delle versioni iOS. Apple pubblica i dati di installazione di iOS alla WWDC e nel dashboard Apple Developer. A giugno 2025, la distribuzione è: iOS 15 — ~7%, iOS 16 — ~48%, iOS 17 — ~35%, iOS 18 — ~10%. Scegliere Target 16.0 fornisce l'83% di copertura, Target 17.0 — 35%. Per le applicazioni di massa (social network, messaggistica, e-commerce), si raccomanda Target 16.0. Per applicazioni B2B di nicchia con API specifiche — Target 17.0.
Il secondo fattore — API richieste. Se la funzionalità principale dell'applicazione richiede SwiftData (iOS 17+), Observation (iOS 17+) o Live Activities (iOS 16.1+), il Target non può essere inferiore alla versione richiesta. Analizzare le API richieste in fase di progettazione previene la situazione in cui a metà dello sviluppo si scopre che è necessario un Target più alto. Utilizzare i controlli di disponibilità come piano di backup, non come strategia principale.
Il terzo fattore — risorse di test. Supportare versioni iOS vecchie richiede test su simulatori e dispositivi reali con tali versioni. iOS 15 viene testato su iPhone 6s/7, iOS 16 — su iPhone 8/X, iOS 17 — su iPhone XS/XR. Ogni versione aggiuntiva di retrocompatibilità aumenta il tempo di QA. Se il team è piccolo, è ragionevole scegliere un Target 2-3 versioni sotto quella corrente (16.0) — un equilibrio tra copertura e sforzo.
| Tipo di applicazione | Target consigliato | Copertura | Motivazione |
|---|---|---|---|
| Di massa (social, marketplace) | iOS 16.0 | ~83% | Pubblico massimo |
| Enterprise / B2B | iOS 16.0 | ~83% | I dispositivi aziendali si aggiornano lentamente |
| Startup / MVP | iOS 17.0 | ~35% | Sviluppo rapido su nuove API |
| Giochi (Metal 3+) | iOS 17.0 | ~35% | Richiedono nuove API grafiche |
| Libreria/SDK | iOS 15.0 | ~90% | Massima compatibilità per i clienti |
Le librerie e gli SDK dovrebbero avere il Deployment Target più basso possibile (15.0 o addirittura 14.0) — i consumatori della libreria possono avere qualsiasi Target superiore al vostro. Se una libreria richiede iOS 17.0, metà dei progetti non potrà utilizzarla. Per le applicazioni, invece, ci si può permettere un Target più alto per accedere a nuove API.
Ridurre l'iOS Deployment Target è un compito che sorge quando è necessario espandere il pubblico o quando si pubblica una libreria con compatibilità per progetti vecchi. A differenza dell'aumento, la riduzione richiede un lavoro attivo sul codice: è necessario sostituire tutte le chiamate dirette alle API non disponibili nel nuovo Target (più basso) con controlli #available e implementazioni di fallback.
Il primo passo — inventario delle API. Xcode non mostra errori di compilazione quando si riduce il Target — avverte solo con avvisi gialli. È necessario trovare tutti i metodi e le classi contrassegnati con @available(iOS N+, *) dove N è superiore al nuovo Target. Utilizzare la ricerca nel progetto (Cmd+Shift+F) con il pattern "available(iOS". Ciascuna di queste chiamate è candidata per il refactoring.
Il secondo passo — sostituzione con controlli #available. Ogni chiamata API da una versione superiore viene racchiusa in if #available(iOS N+, *) { } else { }. Per intere classi, utilizzare #if os(iOS) con @available a livello di tipo. Se un'API non ha un fallback ragionevole (ad esempio, Live Activities), la funzionalità viene disattivata per le versioni vecchie con notifica all'utente.
import UIKit
import SwiftUI
// Riduzione del Deployment Target da 17.0 a 16.0
// PRIMA (@available iOS 17.0):
@available(iOS 17.0, *)
func setupObservation() {
// Observation framework — solo iOS 17+
let model = ObservationViewModel()
// ...
}
// DOPO (controllo #available):
func setupObservationCompatible() {
if #available(iOS 17.0, *) {
// iOS 17+: Observation framework
let model = ObservationViewModel()
// ...
} else {
// iOS 16.x: ObservableObject con @Published
let model = LegacyObservableViewModel()
// ...
}
}
// Per API UIKit iOS 17+:
@available(iOS 17.0, *)
class ModernViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Usa UIKit TraitChanges (iOS 17+)
registerForTraitChanges([UITraitVerticalSizeClass.self]) { _, _ in }
}
}
// Fallback per iOS 16:
class LegacyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Nessun registerForTraitChanges — utilizzo di traitCollectionDidChange
}
override func traitCollectionDidChange(_: UITraitCollection?) {
super.traitCollectionDidChange(nil)
// Gestione cambiamenti traits per iOS 16
}
}
// Factory per selezionare implementazione per versione iOS
func makeViewController() -> UIViewController {
if #available(iOS 17.0, *) {
return ModernViewController()
} else {
return LegacyViewController()
}
}Il codice dimostra la riduzione del Target da iOS 17.0 a 16.0. La funzione setupObservation viene sostituita con setupObservationCompatible con un controllo #available. Il ViewController viene diviso in Modern (iOS 17+) e Legacy (iOS 16) con una factory makeViewController che seleziona l'implementazione in base alla versione del SO. Questa architettura consente di supportare due Deployment Target senza duplicare l'intera base di codice — solo moduli con versione.
Dopo aver ridotto il Deployment Target, Xcode evidenzierà in giallo tutte le chiamate API non disponibili nel nuovo Target. L'avviso "In iOS 16.0 and later" significa che il metodo richiede una versione superiore. Soluzioni: aggiungere @available o if #available (consigliato), sopprimere tramite @available(*, deprecated) per migrazione graduale, o rimuovere la chiamata. Abilitare "Treat Warnings as Errors" nel progetto trasformerà questi avvisi in errori di compilazione — abilitare questa opzione per il controllo.
Domande frequenti
iOS Deployment Target è la versione minima di iOS su cui un'applicazione può essere eseguita. Viene specificato in Xcode Project → Info → iOS Deployment Target. Un'app con Target 16.0 non può essere installata su iOS 15.0 e inferiore. L'App Store filtra le applicazioni in base a questo parametro — gli utenti con versioni non supportate non vedono l'app. L'equivalente in Android è minSdkVersion.
Entrambi i parametri impostano la versione minima del SO per installare un'applicazione. iOS Deployment Target è memorizzato in Info.plist (MinimumOSVersion), minSdkVersion — in AndroidManifest.xml. iOS non ha equivalenti per targetSdkVersion e compileSdkVersion — tutti i cambiamenti comportamentali vengono applicati durante la compilazione con il nuovo Base SDK. In Android, i cambiamenti comportamentali sono controllati tramite targetSdkVersion. Controlli nel codice: @available in Swift vs Build.VERSION.SDK_INT in Android.
Si consiglia di scegliere iOS 16.0 per le applicazioni di massa (83% dei dispositivi) e iOS 17.0 per startup e progetti che utilizzano SwiftUI Observation/SwiftData (35% dei dispositivi). iOS 16.0 è supportato su iPhone 8 e successivi, include SwiftUI Layout, NavigationStack, Live Activities. iOS 17.0 fornisce Observation, SwiftData, TipKit. Per librerie e SDK — iOS 15.0 per la massima compatibilità.
In Swift, utilizzare #available(iOS 17.0, *) all'interno delle funzioni per l'esecuzione condizionale del codice o @available(iOS 17.0, *) a livello di classe/metodo per il controllo dichiarativo. Per la versione esatta — ProcessInfo.processInfo.operatingSystemVersion, che restituisce OperatingSystemVersion. In Objective-C, utilizzare @available(iOS 17.0, *) all'interno di if. Senza controlli, chiamare un API al di sopra del Deployment Target provoca un crash in fase di esecuzione.
È possibile ridurre il iOS Deployment Target, ma richiede la sostituzione di tutte le chiamate API dirette da versioni superiori con controlli #available e implementazioni di fallback. Xcode avvertirà con avvisi gialli ma non mostrerà un errore. Le API senza un fallback ragionevole (Live Activities, SwiftData) vengono disattivate sulle versioni vecchie. Si consiglia di iniziare con un Target 2 versioni sotto quella corrente per evitare una migrazione complessa.
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