Table of Contents
SwiftUI, il framework di Apple per la costruzione di interfacce utente su tutte le piattaforme Apple, fornisce un modo potente ma semplice per creare interfacce multi-tab. La navigazione a schede è uno dei modelli più comuni nelle applicazioni mobili e desktop, permettendo agli utenti di passare rapidamente tra sezioni distinte senza perdere contesto.
Questo articolo passa attraverso tutto quello che dovete sapere sulla progettazione di interfacce multi-tab con SwiftUI. A partire dalle basi di TabView[[], esploreremo la personalizzazione, la gestione dello stato, i modelli avanzati, l'accessibilità, le prestazioni e gli esempi del mondo reale.
Comprendere il componente TabView
Al centro della navigazione a schede in SwiftUI si trova TabView. È una visualizzazione del contenitore che presenta una serie di viste dei bambini, ognuna associata a una voce di scheda. Quando l'utente tocca una scheda, viene visualizzata la vista corrispondente, e la barra delle schede mostra lo stato attivo con un'evidenziazione.
Layout e comportamento
Per impostazione predefinita, TabView[] rende una barra di linguetta in basso sullo schermo su iOS e in alto su macOS. iPadOS si adatta all'orientamento del dispositivo, e watchOS utilizza uno stile segmentato. Non è necessario gestire il layout della barra di scheda stessa; SwiftUI gestisce il posizionamento, dimensionamento e animazione della selezione della scheda.
Articoli di scheda con simboli SF
Apple consiglia l'utilizzo di simboli SF per le icone della scheda perché si scalano perfettamente attraverso i dispositivi e le impostazioni di accessibilità. Il modificatore accetta un view builder dove tipicamente si posiziona un con un nome SF Symbol e un ] etichetta.
TabView {
ContentView()
.tabItem {
Label("Home", systemImage: "house.fill")
}
}
La vista Label[]] combina automaticamente un'icona e un titolo, garantendo un corretto allineamento e etichette di accessibilità.
Costruire un'interfaccia multi-tab di base
Creare una semplice app a schede richiede solo alcune linee di codice. Costruiremo un esempio minimo con tre schede: Casa, Ricerca e Profilo.
Attuazione passo passo passo passo
- Creare una nuova vista SwiftUI (ad esempio, ) e aggiungere un TabView] come radice.
- Per ogni scheda, fornire una vista del bambino (come un o una vista personalizzata).
- Attaccare il modificatore con un Simbolo SF appropriato e una stringa localizzata.
Codice Esempio
struct ContentView: View {
var body: some View {
TabView {
HomeView()
.tabItem {
Label("Home", systemImage: "house.fill")
}
SearchView()
.tabItem {
Label("Search", systemImage: "magnifyingglass")
}
ProfileView()
.tabItem {
Label("Profile", systemImage: "person.crop.circle")
}
}
}
}
struct HomeView: View {
var body: some View {
Text("Welcome Home")
}
}
struct SearchView: View {
var body: some View {
Text("Find what you need")
}
}
struct ProfileView: View {
var body: some View {
Text("Your profile")
}
}
Questo codice produce una barra delle schede di lavoro con tre elementi. Ogni scheda mostra il relativo contenuto quando selezionato. SwiftUI gestisce automaticamente le animazioni di stato attivo e di transizione.
Personalizzando gli articoli della scheda
Mentre l'aspetto predefinito è pulito, spesso è necessario personalizzare la barra delle schede per abbinare il marchio della tua app o fornire feedback extra dell'utente.
Aggiungere Badges e Indicatori
SwiftUI consente di fissare un badge a qualsiasi elemento di scheda utilizzando il modificatore [ sulla vista del bambino. I malghe visualizzano un piccolo numero o un testo (come il numero di notifiche non lette).
TabView {
InboxView()
.tabItem { Label("Inbox", systemImage: "tray.fill") }
.badge(5) // Shows a red badge with "5"
SettingsView()
.tabItem { Label("Settings", systemImage: "gearshape") }
}
I malviventi si aggiornano automaticamente quando si è legati a un []@State[]] o a una proprietà osservata. Su iOS, il badge appare come un cerchio rosso con un numero; su altre piattaforme, può rendere in modo diverso.
Aspetto della barra delle schede di cambiamento (colori e sfondo di vernice)
Per modificare il colore dell'accento della scheda selezionata, impostare il modificatore sul [TabView[] (deprecato nelle versioni iOS più recenti) o utilizzare il modificatore in iOS 15+:
TabView {
// tabs...
}
.tint(.purple)
Per una personalizzazione più avanzata, come uno sfondo o una forma personalizzata, è possibile utilizzare attraverso [] o costruire una barra di schede completamente personalizzata utilizzando uno stack orizzontale di pulsanti (vedere la sezione barra di scheda personalizzata in seguito). Tuttavia, attaccare alla barra di scheda di sistema quando possibile assicura un comportamento coerente con le aspettative degli utenti e gesti di livello di sistema.
Gestione dello Stato e della Selezione
Controllare quale scheda è attiva è essenziale per le caratteristiche come il collegamento profondo, le preferenze dell'utente, o ripristinare l'applicazione alla prima scheda dopo una determinata azione.
Utilizzo di @State per la selezione
Blegate una variabile @State[[]] dello stesso tipo di valori del tag al parametro [ di [TabView]]. Assegnate a ciascun bambino di visualizzare un intero (o qualsiasi valore)]) utilizzando il modificatore.
struct ContentView: View {
@State private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
HomeView()
.tabItem { Label("Home", systemImage: "house.fill") }
.tag(0)
SearchView()
.tabItem { Label("Search", systemImage: "magnifyingglass") }
.tag(1)
ProfileView()
.tabItem { Label("Profile", systemImage: "person.crop.circle") }
.tag(2)
}
}
}
Quando ] cambia (ad esempio, tramite un pulsante sulla schermata iniziale), la visualizzazione della scheda passa automaticamente alla scheda corrispondente. Questo approccio consente anche di leggere la scheda corrente altrove nella tua app.
Commutazione della scheda programmatica
È possibile modificare le schede dall'interno di qualsiasi visualizzazione del bambino passando un binding alla variabile di selezione. Ad esempio, un pulsante "Vai a Impostazioni" sulla scheda di casa:
struct HomeView: View {
@Binding var selectedTab: Int
var body: some View {
VStack {
Text("Home")
Button("Open Settings") {
selectedTab = 2
}
}
}
}
Integrare questo passando il legame quando si crea la vista del bambino all'interno del [TabView[]. Questo ti dà il pieno controllo sulla navigazione senza rompere lo stato della scheda.
Selezione di schede persistente con UserDefaults
Per un tocco facile da usare, ricorda l'ultima scheda selezionata dopo il riavvio dell'app. Usa per persistere automaticamente la selezione a UserDefaults[:
struct ContentView: View {
@AppStorage("selectedTab") private var selectedTab = 0
var body: some View {
TabView(selection: $selectedTab) {
// tabs...
}
}
}
L'app verrà ora lanciato sulla scheda l'utente ha visitato l'ultima volta.
Modelli di navigazione avanzati
Le app multi-tab spesso hanno bisogno di integrare con stack di navigazione, gestire URL in arrivo o condividere dati tra le schede.
Combinando TabView con NavigationView
Ogni scheda può contenere la propria (o nella più vecchia SwiftUI) che consente di perforare in dettaglio le viste all'interno di una scheda mentre la barra delle schede rimane visibile.
struct HomeView: View {
var body: some View {
NavigationStack {
List(1..<20) { item in
NavigationLink("Item \(item)", value: item)
}
.navigationDestination(for: Int.self) { item in
DetailView(item: item)
}
.navigationTitle("Home")
}
}
}
Posizionare il all'interno della scheda di visualizzazione del bambino, non al di fuori del [TabView[], per mantenere pile di navigazione separate per scheda.
Gestione dei link profondi
Quando l'app riceve un link universale o uno schema di URL personalizzato, è necessario passare a una scheda specifica e navigare in modo facoltativo a una sotto-visione. Utilizzare il modificatore sul TabView[] (o la visualizzazione root) e analizzare l'URL per aggiornare lo stato di selezione o attivare la navigazione.
TabView(selection: $selectedTab)
.onOpenURL { url in
// e.g., myapp://tab/2
if let tabNumber = extractTab(from: url) {
selectedTab = tabNumber
}
}
Per scenari più complessi, combina con un legame di percorso .
Passare i dati tra le schede
Poiché ogni scheda ha una propria gerarchia di visualizzazione, i dati di passaggio tra di loro richiedono una fonte di stato condivisa.
- Oggetti di ambiente[[]]: iniettare un [] via alla radice del TabView.
- StateObject con un manager condiviso[[: Creare un singolo o una classe osservabile e passarlo giù.
- Utilizzando la selezione binding[[]: Per i valori semplici, lo stato di selezione può agire come canale di comunicazione (ad esempio, “ho passato alla scheda 2 perché i dati sono pronti”).
Evitare sovracomplicazioni; mantenere il flusso di dati unidirezionale quando possibile.
Accessibilità e esperienza utente
SwiftUI fornisce un supporto di accessibilità integrato, ma è necessario verificare e migliorare.
Supporto VoiceOver
Gli elementi della scheda ottengono automaticamente le etichette di accessibilità dal ]Label[]] o il testo che fornisci.
Navigazione tastiera
Su iPadOS con una tastiera hardware, gli utenti possono navigare tra le schede utilizzando Command‐[number] o Option‐Tab. SwiftUI [TabView] eredita automaticamente questo comportamento.
Telaio adattivo
Su iPhone in modalità paesaggio, la barra delle schede può apparire in modo diverso. iOS 15 e poi consentire la barra delle schede di compattare quando lo spazio è limitato. È possibile regolare il contenuto della scheda con per fornire una migliore esperienza di lettura o interazione.
Barra di scheda personalizzata con SwiftUI
A volte è necessario un design che devia dalla barra delle schede di sistema — ad esempio, un pulsante galleggiante nel mezzo, una forma curva, o icone animate. Mentre si perde alcuni comportamenti incorporati (come inserimenti area sicura), SwiftUI rende le barre di scheda personalizzate in modo semplice.
Replicare TabView con forme personalizzate
Creare una visualizzazione personalizzata utilizzando un di pulsanti sovrapposti in basso. Utilizzare [ per la selezione e il contenuto di commutazione con una proprietà calcolata o un dichiarazione all'interno di un .
struct CustomTabView: View {
@State private var selection = 0
var body: some View {
VStack(spacing: 0) {
// Content area
Group {
if selection == 0 {
HomeView()
} else if selection == 1 {
SearchView()
} else {
ProfileView()
}
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
// Custom tab bar
HStack {
TabBarButton(icon: "house.fill", label: "Home", isSelected: selection == 0)
.onTapGesture { selection = 0 }
Spacer()
TabBarButton(icon: "magnifyingglass", label: "Search", isSelected: selection == 1)
.onTapGesture { selection = 1 }
Spacer()
TabBarButton(icon: "person.fill", label: "Profile", isSelected: selection == 2)
.onTapGesture { selection = 2 }
}
.padding(.horizontal)
.padding(.top, 8)
.background(Color(uiColor: .systemBackground)
.shadow(radius: 2))
}
.ignoresSafeArea(.keyboard) // Prevent tab bar from moving with keyboard
}
}
Trasmissioni di schede animate
Aggiungi transizioni lisce quando si passano le schede avvolgendo il contenuto in un blocco [. Ad esempio, aggiungere una diapositiva o una transizione opacità. È inoltre possibile animare l'icona stessa utilizzando su iOS 17+ (come rimbalzo o polso).
Ottimizzazione delle prestazioni
Le app multi-tab possono soffrire di bloat di memoria se caricate tutte le schede con entusiasmo. SwiftUI [TabView[] è pigro per impostazione predefinita: crea e rende la vista solo per la scheda selezionata. Tuttavia, se utilizzate viste acustiche, potreste ancora voler ottimizzare.
Contenuto della scheda di caricamento pigro
Utilizzare o all'interno delle schede per differire la creazione della vista fino a scorrere. Evitare di usare calcoli complessi nell'inizialezzatore delle viste dei bambini scheda; invece, fare affidamento su per avviare il caricamento dei dati.
Evitare le perdite di memoria
Poiché le schede spesso contengono riferimenti a istanze, assicurarsi che non si sta creando cicli di riferimento forti inutili. Utilizzare [ per oggetti di proprietà e per quelli condivisi. Se una scheda non è mai mostrata, la sua vista può essere mantenuta in memoria - utilizzare (un wrapper personalizzato) per differire l'inizial'inizial'inizializzazione fino alla scheda è selezionata.
Testare l'interfaccia Tabbed
I test automatizzati aiutano a garantire che la navigazione a schede funzioni correttamente attraverso gli stati dei dispositivi.
Test unità per la selezione del tab
Poiché la visualizzazione della scheda è guidata da una variabile , è possibile testare la logica che cambia []. Ad esempio, convalidare che un link profondo correttamente si analizza e assegna l'indice della scheda.
func testTabSelectionViaDeepLink() {
let url = URL(string: "myapp://tab/2")!
let tabNumber = extractTab(from: url)
XCTAssertEqual(tabNumber, 2)
}
Test dell'interfaccia utente con XCTest
Utilizzare XCUITest per verificare che la mappatura di un elemento di scheda visualizza il contenuto corretto.
func testTappingSearchTab() {
let app = XCUIApplication()
app.launch()
let searchTab = app.tabBars.buttons["Search"]
XCTAssertTrue(searchTab.exists)
searchTab.tap()
XCTAssertTrue(app.staticTexts["Find what you need"].exists)
}
Esempio di Real‐World: un Dashboard multi-Tab
Portiamo tutto insieme con un esempio pratico: un'applicazione dashboard con tre schede — Panoramica, Analytics e Impostazioni.
Scheda panoramica
Mostra un riassunto delle metriche chiave (come gli utenti attivi giornalieri, i ricavi) in un scorrimento . Utilizza ] per consentire la perforazione in report dettagliati. La selezione della scheda è persistita con .
Scheda di analisi
Contiene grafici e grafici costruiti con Swift Charts. Poiché il rendering grafico può essere pesante, contrassegnare la vista come [ e attivare il caricamento dei dati solo quando la scheda appare.
Scheda delle impostazioni
Visualizza un elenco di attivazioni, link e un pulsante logout. Questa scheda potrebbe essere necessario accedere a un oggetto ambientale contenente la sessione dell'utente. Passando che via assicura che tutte le schede condividano gli stessi dati.
Pitfalls e soluzioni comuni
Anche gli sviluppatori SwiftUI esperti si esibiscono in alcuni problemi ricorrenti con [TabView.
Barra di scheda Scomparsa in Navigazione Stack
Se si preme una vista su uno stack di navigazione all'interno di una scheda, la barra delle schede può sparire su push. Soluzione: utilizzare [[ (iOS 16+) invece di [] – la barra delle schede rimane visibile. In alternativa, nascondere / mostrare manualmente la barra delle schede utilizzando il modificatore.
Valori tag non corretti
Se non assegnate a ogni bambino, la vista della scheda non può onorare correttamente la selezione vincolante.
Visualizza scheda Stato di ripristino
A volte quando si passano le schede, lo stato della vista del bambino si resetta. Questo è per design – SwiftUI crea una nuova istanza della vista del bambino ogni volta che ha bisogno di visualizzarlo. Per preservare lo stato attraverso gli switch, sollevare lo stato in una vista del genitore o utilizzare a un livello sopra il TabView].
Conclusioni
La progettazione di un'interfaccia multi-tab con SwiftUI è sia semplice che profondamente personalizzabile. Il componente TabView vi dà una solida base, e con alcune linee di codice aggiuntive è possibile aggiungere distintivi, gestire lo stato, integrare stack di navigazione e anche costruire barre di schede completamente personalizzate.
Continuate ad esplorare immergendosi nella documentazione ufficiale di TabView , imparando linee guida dell'interfaccia umana per le barre a schede[], e sperimentando con ] FLT[]]]]] per dare alle vostre schede un look lucido e coerente.