XCFramework è un formato binario Apple che combina librerie per iOS, macOS, tvOS e watchOS in un singolo pacchetto. È stato progettato per sostituire .framework ed eliminare i problemi dei fat binaries durante la compilazione per diverse architetture di simulatore e dispositivo. Secondo Apple WWDC 2019, XCFramework è diventato il formato obbligatorio per la distribuzione di SDK che supportano più piattaforme, sostituendo completamente l'approccio obsoleto dei binari universali.
Punti chiave
XCFramework è un formato di impacchettamento per librerie e framework binari presentato da Apple al WWDC 2019. L'obiettivo principale è creare un unico bundle che contenga versioni compilate di una libreria per tutte le piattaforme e architetture di destinazione.
Prima di XCFramework, gli sviluppatori utilizzavano .framework con fat binary che combinavano più architetture tramite l'utilità lipo. Questo approccio causava problemi: durante la compilazione di un progetto per il simulatore, il fat binary conteneva sia l'architettura del simulatore che quella del dispositivo, causando errori durante l'invio della build all'App Store. Gli sviluppatori dovevano scrivere fasi Run Script per rimuovere le architetture non necessarie.
Secondo la Documentazione per Sviluppatori Apple (2024), XCFramework supporta tutte le piattaforme dell'ecosistema Apple: iOS, iPadOS, macOS, tvOS, watchOS, visionOS e applicazioni Catalyst. Ogni piattaforma riceve uno slice separato all'interno del pacchetto, eliminando i conflitti di architettura e semplificando la distribuzione degli SDK.
XCFramework viene utilizzato in tre scenari principali: distribuzione di SDK chiusi a sviluppatori terzi, distribuzione di moduli nativi per Flutter e React Native e pubblicazione di librerie che richiedono precompilazione. Il formato è obbligatorio per tutti i nuovi SDK pubblicati nell'ecosistema Apple.
Gli sviluppatori scelgono XCFramework quando il codice sorgente non può essere divulgato, quando la libreria utilizza algoritmi proprietari o quando è richiesta protezione di licenza. A differenza di Swift Package Manager, che funziona con codice sorgente, XCFramework fornisce file binari già compilati.
Il problema del fat binary era che un binario universale conteneva più architetture in un singolo file Mach-O. Durante la compilazione di un'app per il simulatore, Xcode includeva sia l'architettura arm64 del dispositivo che l'architettura x86_64 del simulatore — l'App Store accettava solo l'architettura del dispositivo.
La soluzione tradizionale prevedeva l'aggiunta di una fase Run Script che chiamava lipo per rimuovere le architetture del simulatore dalla build finale. Questo approccio era fragile e si rompeva con gli aggiornamenti di Xcode o con l'arrivo di nuove architetture (ad esempio, arm64 per il simulatore su Apple Silicon).
Secondo Swift.org (2023), il team di Swift Package Manager ha inizialmente incontrato questo problema nel tentativo di supportare le dipendenze binarie. XCFramework lo ha risolto a livello di formato: ogni slice è una cartella separata con un Info.plist che descrive la piattaforma e l'architettura di destinazione. Xcode seleziona automaticamente lo slice necessario durante la compilazione, senza richiedere post-elaborazione.
Ogni slice in XCFramework contiene una sola combinazione piattaforma-architettura. Ad esempio, ios-arm64 contiene il binario solo per dispositivi iOS e ios-x86_64-simulator solo per il simulatore Intel Mac. Xcode seleziona automaticamente lo slice corretto, eliminando la necessità di script di rimozione delle architetture e riducendo il rischio di errori di compilazione.
Lo slice ios-arm64-x86_64-simulator è stato introdotto per supportare i Mac Apple Silicon. In precedenza, il simulatore richiedeva un binario separato per arm64 (Apple Silicon) e x86_64 (Intel). XCFramework consente un fat binary all'interno di un singolo slice del simulatore — questa è l'unica eccezione in cui il fat binary è giustificato.
Un pacchetto XCFramework è una directory con estensione .xcframework, contenente un Info.plist al livello superiore e cartelle con slice binari. Ogni slice include una libreria .framework o .a per una piattaforma specifica.
MyLibrary.xcframework/
Info.plist
ios-arm64/
MyLibrary.framework/
Info.plist
MyLibrary
ios-x86_64-simulator/
MyLibrary.framework/
Info.plist
MyLibrary
macos-arm64-x86_64/
MyLibrary.framework/
Info.plist
MyLibrary
L'Info.plist del pacchetto contiene la chiave AvailableLibraries, che elenca LibraryIdentifier, LibraryPath e SupportedPlatform per ogni slice. Xcode legge questo file quando aggiunge un XCFramework al progetto e configura automaticamente i percorsi di ricerca e la fase Embed Frameworks.
Ogni slice è un .framework completo o una libreria statica con il proprio Info.plist. Ciò consente a XCFramework di supportare tipi misti: librerie statiche per alcune piattaforme e framework dinamici per altre, sebbene in pratica venga utilizzato un tipo per tutti gli slice.
La creazione di un XCFramework avviene tramite xcodebuild -create-xcframework. Il comando prende librerie .framework o .a già compilate per ogni piattaforma e le combina in un unico pacchetto.
Il processo consiste in due passaggi: prima, i binari vengono compilati per ogni piattaforma di destinazione, poi vengono impacchettati in un XCFramework. Per la compilazione vengono utilizzati i flag di destinazione standard di Xcode.
# Step 1: build frameworks for each platform
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS Simulator"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=iOS"
xcodebuild archive -scheme MyLibrary -destination "generic/platform=macOS"
# Step 2: create XCFramework
xcodebuild -create-xcframework -framework ./iOS/MyLibrary.framework -framework ./iOSSim/MyLibrary.framework -framework ./macOS/MyLibrary.framework -output ./MyLibrary.xcframework
Il flag -create-xcframework è stato introdotto in Xcode 11. Il comando crea automaticamente la struttura di directory corretta e genera un Info.plist con la descrizione di tutte le piattaforme. Se uno dei .framework è danneggiato o compilato con l'architettura sbagliata, xcodebuild emette un errore nella fase di validazione.
Per CI/CD, viene utilizzato uno script shell che automatizza la compilazione per tutte le piattaforme e la creazione dell'XCFramework. Un approccio popolare è un wrapper sotto forma di Makefile o Fastlane lane con parametrizzazione dello scheme e del percorso di output.
# build_xcframework.sh - automation script
set -e
SCHEME="MyLibrary"
OUTPUT="./build"
xcodebuild archive -scheme "$SCHEME" -sdk iphonesimulator -archivePath "$OUTPUT/sim.xcarchive"
xcodebuild archive -scheme "$SCHEME" -sdk iphoneos -archivePath "$OUTPUT/dev.xcarchive"
xcodebuild -create-xcframework -framework "$OUTPUT/dev.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -framework "$OUTPUT/sim.xcarchive/Products/Library/Frameworks/MyLibrary.framework" -output "$OUTPUT/MyLibrary.xcframework"
Questo script viene eseguito in una pipeline CI (GitHub Actions, Bitrise, Jenkins) dopo il superamento dei test. L'XCFramework risultante viene archiviato e caricato come artefatto di rilascio o pubblicato tramite un gestore di dipendenze come CocoaPods utilizzando pod spec.
Integrare un XCFramework in un progetto Xcode non richiede la configurazione manuale dei percorsi di ricerca. Basta trascinare il .xcframework nella sezione Frameworks, Libraries, and Embedded Content nelle impostazioni Generali del target.
A differenza di .framework, XCFramework non richiede l'aggiunta di una fase Run Script per rimuovere le architetture del simulatore. Xcode determina automaticamente gli slice disponibili e include solo quelli necessari per lo schema di compilazione corrente. Per un dispositivo fisico viene utilizzato lo slice ios-arm64, per il simulatore — ios-arm64-x86_64-simulator o ios-x86_64-simulator.
import MyLibrary
func processData() {
// XCFramework resolves the correct slice at build time
let processor = DataProcessor()
let result = processor.analyze(input: "sample")
print(result)
}
Per CocoaPods, l'integrazione avviene tramite un podspec con vendored_frameworks e un elenco di piattaforme supportate. Il gestore di dipendenze determina automaticamente quali slice sono necessari per il progetto. Molti SDK commerciali — Firebase, Adjust, AppsFlyer — sono passati a XCFramework per semplificare l'installazione.
Swift Package Manager e XCFramework non sono concorrenti ma si completano a vicenda. SPM funziona con codice sorgente e compila le dipendenze a ogni compilazione del progetto. XCFramework fornisce binari pronti senza richiedere compilazione sul lato consumatore.
Con il rilascio di Swift Package Manager 5.3, Apple ha aggiunto il supporto per le dipendenze binarie — ora SPM può scaricare un XCFramework come dipendenza remota. Package.swift specifica l'URL dell'artefatto binario e il suo checksum per la verifica.
Secondo la documentazione di Swift Package Manager (2024), le dipendenze binarie sono consigliate per SDK che non divulgano il codice sorgente o per librerie il cui tempo di compilazione è sproporzionatamente lungo. Per i progetti open source, si preferisce la distribuzione del codice sorgente tramite SPM.
| Criterio | XCFramework | Swift Package Manager |
|---|---|---|
| Formato | Binario (.xcframework) | Codice sorgente |
| Protezione del codice | Completa | Nessuna |
| Tempo di compilazione | Minimo (copia) | Dipende dal volume di codice |
| Flessibilità delle piattaforme | Tutte le piattaforme Apple | Dipende da Package.swift |
| Integrazione | Trascina e rilascia o SPM | Package.swift |
Domande frequenti
.framework è un formato legacy che contiene un fat binary con architetture del dispositivo e del simulatore. XCFramework memorizza ogni slice separatamente, eliminando i conflitti di architettura durante la compilazione. Apple raccomanda XCFramework per tutti i nuovi progetti e per la migrazione di quelli esistenti.
CocoaPods supporta XCFramework dalla versione 1.9. Nel podspec, è sufficiente specificare spec.vendored_frameworks e spec.static_framework. Il gestore risolve automaticamente le dipendenze, tenendo conto degli slice disponibili per la piattaforma del progetto.
Apple non rimuove il supporto per .framework, ma raccomanda esclusivamente XCFramework per i nuovi SDK. Quando si invia un'app all'App Store con un fat binary nel vecchio formato, possono verificarsi errori Invalid Bundle a causa delle architetture del simulatore, rendendo XCFramework una necessità pratica.
A partire da Swift 5.3, le dipendenze binarie in SPM utilizzano XCFramework. Package.swift specifica l'url e il checksum del pacchetto binario. SPM scarica, verifica l'integrità e connette l'XCFramework come dipendenza di sistema senza compilare il codice sorgente.
visionOS è supportato in XCFramework a partire da Xcode 15. Al WWDC 2023, Apple ha confermato che il formato è stato esteso per Apple Vision Pro. Lo slice per visionOS ha SupportedPlatform = xros e include l'architettura arm64.
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.