Punti chiave
View Protocol è il protocollo centrale di SwiftUI. Richiede una sola proprietà: var body: some View. body è una proprietà calcolata che restituisce la descrizione dell'interfaccia. SwiftUI chiama body ad ogni cambiamento di stato e renderizza il risultato sulla GPU.
@ViewBuilder è un Result Builder per View. Permette di scrivere più View all'interno di una closure senza return e senza TupleView. Supporta if/else, switch, ForEach. Tutti i contenitori (VStack, HStack, ZStack, Group) usano @ViewBuilder. Un'alternativa è Group { … } per raggruppare senza layout. some View è un Opaque Type. Il compilatore conosce il tipo concreto di View (Text, Button, VStack, ecc.), ma lo restituisce esternamente come some View. Questo permette di cambiare il tipo di body senza modificare la firma. ViewModifier — modificatore di View: .font(), .padding(), .background(). Modificatore personalizzato tramite ViewModifier protocol e .modifier().
// Esempio di View con @ViewBuilder e NavigationStack
struct ContentView: View {
@State private var items = ["Item 1", "Item 2"]
var body: some View {
NavigationStack {
List(items, id: .self) { item in
NavigationLink(item) {
DetailView(item: item)
}
}
.navigationTitle("Items")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button("Add") {
items.append("New Item")
}
}
}
}
}
}
// DetailView con @StateObject
struct DetailView: View {
let item: String
@StateObject private var viewModel = DetailViewModel()
var body: some View {
Text(item)
.task {
await viewModel.loadDetails(for: item)
}
}
}NavigationStack (iOS 16+) — navigazione basata sui dati. Prende un percorso (array di valori hashable) e mostra la destinazione tramite navigationDestination. Sostituisce NavigationLink con viste di destinazione. NavigationLink — pulsante per navigare nello stack. List — elenco verticale con sezioni, swipe, eliminazione e trascinamento. Form — una List specializzata per impostazioni: sezioni, selettori, interruttori, campi di testo. Section — raggruppamento in List/Form con intestazione e piè di pagina. ViewModifier — modificatori personalizzati per riutilizzare stili. .modifier(CustomModifier()) — applicazione.
List in SwiftUI è l'equivalente di UITableView. Supporta .onDelete, .onMove, .refreshable. SwipeActions — .swipeActions { Button("Elimina", role: .destructive) { } }. Form — ottimizzato per impostazioni: DatePicker, Toggle, Stepper, Picker. Section con header/footer — per raggruppare. OutlineGroup — elenchi gerarchici (equivalente di UITableView con sezioni). DisclosureGroup — sezione richiudibile con contenuto. IT Sectr raccomanda List per i dati e Form per le impostazioni.
PreviewProvider — protocollo per anteprime in Xcode Canvas. Canvas — anteprima interattiva di SwiftUI (richiede @main e Swift 5.9+). @ScaledMetric — dimensione adattiva che scala con Dynamic Type.
Property Wrappers sono la base della gestione dello stato in SwiftUI. @State — stato locale (value type). @Binding — connessione allo stato genitore. @StateObject — crea un ObservableObject. SwiftUI gestisce il ciclo di vita dell'oggetto. @ObservedObject — osserva un ObservableObject esterno. @EnvironmentObject — oggetto dall'ambiente (dependency injection tramite .environmentObject()). @Environment — valori di sistema (.colorScheme, .locale). @AppStorage — UserDefaults. @FetchRequest — query Core Data. @FocusState — focus di input.
| Wrapper | Scopo | Proprietà |
|---|---|---|
| @State | Stato locale (value type) | La View possiede |
| @Binding | Connessione allo stato genitore | Il genitore possiede |
| @StateObject | Crea ObservableObject | La View possiede |
| @ObservedObject | Osserva oggetto esterno | Proprietario esterno |
| @EnvironmentObject | Oggetto dall'ambiente | L'antenato possiede |
| @Environment | Valore di sistema | Il sistema |
| @AppStorage | UserDefaults | UserDefaults |
| @FocusState | Focus di input | La View possiede |
@StateObject vs @ObservedObject: @StateObject crea un oggetto, @ObservedObject lo osserva. Usa @StateObject per la creazione iniziale del modello nella gerarchia, @ObservedObject per passare alle viste figlie. @FocusState — gestione del focus: .focused($field, equals: .email). Supporta enum per più campi.
@Environment — valori di sistema: colorScheme, locale, sizeCategory, layoutDirection, managedObjectContext. Valori di ambiente personalizzati — valore personalizzato tramite EnvironmentKey. Utilizzato per dependency injection: passare servizi senza parametri espliciti. Modificatore .environment() — imposta un valore nella gerarchia. @EnvironmentObject — ObservableObject da .environmentObject(). Differisce da @Environment in quanto passa un tipo per riferimento. IT Sectr raccomanda @Environment per i valori di sistema e @EnvironmentObject per i servizi.
.task{} — operazione asincrona all'apparizione della vista. Cancellazione automatica alla scomparsa. Sostituisce .onAppear per async/await. .onAppear{} — operazione sincrona all'apparizione. .onDisappear{} — operazione alla scomparsa. .onChange(of:) — reazione ai cambiamenti di valore. .onReceive(Publisher) — reazione al publisher Combine. Ciclo di vita della View in SwiftUI: init → onAppear → body (rendering) → onDisappear. Al cambiamento di stato: body → diff → re-rendering. IT Sectr raccomanda .task per il caricamento asincrono e .onAppear per le analisi.
.animation() — modificatore di animazione. .transition() — animazione di apparizione/scomparsa. withAnimation — animazione esplicita dei cambiamenti di stato. matchedGeometryEffect — animazione tra viste diverse (hero animation). PhaseAnimator (iOS 17+) — animazione multifase basata su enum. KeyframeAnimator (iOS 17+) — animazione fotogramma per fotogramma con keyframes. Le animazioni SwiftUI vengono eseguite sulla GPU tramite Core Animation. IT Sectr raccomanda .spring() per animazioni naturali e .interpolatingSpring per effetti fisici.
ObservableObject — protocollo per oggetti con proprietà @Published. SwiftUI si abbona al publisher objectWillChange. @Published — pubblica i cambiamenti di proprietà. @StateObject — crea ObservableObject, gestisce il ciclo di vita. @ObservedObject — osserva esterno. Combine — framework per la programmazione reattiva. @EnvironmentObject — DI tramite ambiente. .environmentObject() imposta, @EnvironmentObject legge. MVVM — architettura standard: View (SwiftUI) — ViewModel (ObservableObject) — Model. IT Sectr raccomanda MVVM + @StateObject per i ViewModel principali.
class UserViewModel: ObservableObject {
@Published var users: [User] = []
@Published var isLoading = false
func loadUsers() async {
isLoading = true
defer { isLoading = false }
do {
users = try await api.fetchUsers()
} catch {
print("Errore: \(error)")
}
}
}
struct UsersView: View {
@StateObject private var viewModel = UserViewModel()
var body: some View {
List(viewModel.users, id: \.id) { user in
Text(user.name)
}
.task { await viewModel.loadUsers() }
.overlay {
if viewModel.isLoading { ProgressView() }
}
}
}Accessibilità in SwiftUI: .accessibilityLabel(), .accessibilityHint(), .accessibilityValue(), .accessibilityAddTraits(). VoiceOver legge le etichette di accessibilità. Dynamic Type — @ScaledMetric, @DynamicProperty. Localizzazione: String(localized:) (SwiftUI + String Catalog). LocalizedStringKey — traduzione automatica. Regole plurali — tramite String Catalog (one, few, many, other). Da destra a sinistra (arabo, ebraico) — supportato automaticamente. .environment(.layoutDirection, .rightToLeft). IT Sectr raccomanda etichette di accessibilità per tutti gli elementi interattivi.
struct AccessibleButton: View {
let action: () -> Void
var body: some View {
Button(action: action) {
Label("Settings", systemImage: "gear")
}
.accessibilityLabel("Open Settings")
.accessibilityHint("Double tap to navigate to settings screen")
.accessibilityAddTraits(.isButton)
}
}
// Supporto Dynamic Type
struct ScalableText: View {
@ScaledMetric private var fontSize: CGFloat = 17
var body: some View {
Text("Hello, World!")
.font(.system(size: fontSize))
}
}Swift Charts (iOS 16+) — framework per creare grafici. Chart { } — contenitore base. BarMark, LineMark, PointMark, AreaMark, RuleMark — marcatori. ForEach per i dati. ChartAxis — personalizzazione degli assi. .chartXAxis, .chartYAxis. ChartLegend — legenda. Interpolazione — catmullRom, linear, step. Animazione — .animation() per Chart. IT Sectr raccomanda Swift Charts per grafici integrati e Charts (DGCharts) per quelli complessi.
import Charts
struct MonthlySales: Identifiable {
let id = UUID()
let month: String
let sales: Double
}
struct SalesChart: View {
let data: [MonthlySales]
var body: some View {
Chart(data) { item in
BarMark(
x: .value("Month", item.month),
y: .value("Sales", item.sales)
)
.foregroundStyle(.blue.gradient)
}
.chartXAxisLabel("Month")
.chartYAxisLabel("Sales")
.frame(height: 200)
.padding()
}
}Swift Package Manager (SPM) — il gestore di dipendenze di Apple. Integrato in Xcode. Supporta: pacchetti binari, risorse, test, swift-6 concorrenza rigorosa. Pubblicazione di pacchetti tramite GitHub con tag semver. SPM è lo standard de facto per le dipendenze Swift, sostituendo CocoaPods e Carthage. IT Sectr raccomanda SPM per tutti i nuovi progetti.
Swift Concurrency (async/await, TaskGroup, AsyncSequence) — async/await integrato in Swift 5.5+. Task — unità di asincronia. TaskGroup — attività parallele. AsyncSequence — sequenza asincrona (AsyncStream, AsyncAlgorithms). Task Local Values — dati contestuali per Task. Swift Concurrency sostituisce completamente Combine per le operazioni asincrone.
Domande frequenti
View Protocol è il protocollo base. Richiede var body: some View. body è la descrizione dell'interfaccia renderizzata sulla GPU.
@ViewBuilder è un Result Builder per più View. Permette if/else, switch, ForEach all'interno dei contenitori.
@StateObject crea un oggetto. @ObservedObject ne osserva uno esistente. @StateObject per la prima creazione nella gerarchia.
NavigationStack — navigazione basata sui dati. path-based, deep linking. Sostituisce NavigationView.
@FocusState — gestione del focus di input. Modificatore .focused(). Supporta enum per più campi.
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.