La resizability su iOS: quando un'app non sa più su quale dispositivo gira

Cinque principi di design, ognuno fatto atterrare in codice: nell'era del ridimensionamento, un'app si chiede solo quanto spazio ha. Con configurazione della scena, callback di geometria, strategia a due passaggi, linee rosse Info.plist e matrice di test.

La resizability è la possibilità che la finestra di un'app venga afferrata dal bordo e trascinata liberamente a qualsiasi dimensione, come una finestra desktop. Il pensiero di design che Apple lega a questo cambiamento sta in una frase: un'app non si preoccupa più di sapere su quale dispositivo gira, in quale orientamento, su quale schermo. Le interessa solo quanto spazio ha in quel preciso istante. Tu definisci due comportamenti: come si dispone il contenuto quando c'è più posto e come quando c'è meno. Il sistema applica quella logica su tutti i dispositivi, tutte le dimensioni di finestra e tutte le postura di piega.

Questa non è un ordinario aggiornamento di API. È un cambio di corsia nel paradigma del layout dalla nascita di iOS. Questo articolo scompone il pensiero di design in cinque principi, fa atterrare ciascuno in codice UIKit e SwiftUI, e si chiude con una roadmap di migrazione e una matrice di test da eseguire così come sono.

Le firme nel testo sono confrontate con l'SDK iOS 27.1 di Xcode 27.1. Il comportamento segue la documentazione Apple e le sessioni WWDC, le cui fonti sono elencate in fondo. Il corpo è una riproposizione e un'organizzazione tecnica, non la traduzione di una pagina specifica.

1. Da iOS 26 a 27: come il ridimensionamento è diventato il default

Prima del pensiero di design, la cronologia. Spiega perché il vecchio modo di fare non basta più.

Fase Cosa è successo Cosa significa per te
iPadOS 15 Split View / Slide Over / Stage Manager L'iPad conosce dimensioni diverse dal pieno schermo
iPadOS 26 L'iPad entra nell'era delle finestre libere L'ipotesi «iPad = regular» inizia a vacillare
SDK iOS 26 UIRequiresFullScreen è deprecato Non si esce più dal ridimensionamento col tasto schermo intero
SDK iOS 26 Le app iPhone si ridimensionano anche su iPad e nel mirroring su Mac «Girare su un iPhone» non vuol più dire compact
iOS 27 Il ciclo di vita UIScene è obbligatorio per le build con SDK recente Le scene diventano il fondamento
iOS 27 Tab bar, barre degli strumenti: i componenti di sistema si adattano a ogni proporzione I componenti di sistema fanno il lavoro pesante

Il filo in una frase: la dimensione della finestra è passata da valore enumerato a valore continuo. Prima la tua app affrontava 375, 393, 414, 768, 1024. Ora un dito afferra il bordo della finestra e trascina una volta: la larghezza può essere qualsiasi numero tra 320 e il limite dello schermo. Un layout scritto per gradini discreti si rompe di sicuro contro un valore continuo.

2. Principio uno: dal «pensiero del dispositivo» al «pensiero dello spazio»

La maggior parte della vecchia conoscenza di layout poggia sul pensiero del dispositivo: questo è un iPhone, è in orizzontale, quindi si dispone così; questo è un iPad, quindi si divide in due. La resizability chiede di sostituire quel pensiero per intero.

Pensiero del dispositivo (vecchio) Pensiero dello spazio (nuovo)
Criterio di decisione Tipo di dispositivo, orientamento, dimensione schermo Spazio disponibile del contenitore attuale
Numero di layout Una versione per dispositivo Un solo set di regole per tutti gli spazi
Nuovo hardware Può richiedere codice e una release Si applica da sé, zero cambiamenti
postura di piega Un'interfaccia in più per postura Un'interfaccia che si stira con la larghezza
Puzza nel codice if idiom == .pad, isLandscape horizontalSizeClass, larghezza del contenitore

La formulazione più nuda del pensiero dello spazio viene dalla WWDC: non progetti per ogni piattaforma né per ogni dimensione di finestra. Definisci una volta come si comporta il contenuto quando c'è più posto e quando ce n'è meno. Il sistema applica quella logica a ogni proporzione. Ruotare lo schermo è solo un innesco di quella logica, della stessa natura del trascinare una finestra, dell'entrare in Split View o del dispiegare uno schermo: tutto confluisce nello stesso punto unico: lo spazio disponibile è cambiato.

3. Principio due: le classi di dimensione sono la nuova lingua franca

Quando il pensiero del dispositivo si ritira, chi raccoglie il testimone? La classe di dimensione. È il giudizio qualitativo che il framework dà dello spazio: due assi, due parole per asse: compact significa stretto, regular significa ampio.

  • L'asse orizzontale giudica sinistra e destra: in compact il contenuto deve impilarsi in una colonna; solo in regular le colonne, l'affiancamento e la barra laterale diventano onesti.

  • L'asse verticale giudica sopra e sotto: in compact il chrome verticale (tab bar, barra degli strumenti) non ci sta più, e il sistema drizza una tab bar orizzontale in verticale. In regular, le barre alta e bassa coesistono.

In SwiftUI si legge direttamente:

@Environment(\.horizontalSizeClass) private var hSize  // UserInterfaceSizeClass?
@Environment(\.verticalSizeClass) private var vSize

if hSize == .regular {
    // Posto a sinistra e a destra: colonne / barra laterale / due file
} else {
    // Stretto a sinistra e a destra: una colonna impilata
}

In UIKit, traitCollection.horizontalSizeClass porta lo stesso dovere, e con registerForTraitChanges ci si abbona ai cambiamenti con precisione.

Arriva la tabella più importante di questo articolo: le classi di dimensione non sono in corrispondenza biunivoca con il dispositivo né con l'orientamento:

Scena Orizzontale Verticale Nota
iPhone verticale compact regular La forma predefinita di tutta l'app
iPhone orizzontale compact compact Solo circa 320 pt di altezza, la barra passa in verticale
Finestra iPhone ingrandita (iOS 26+) regular regular Cambia in runtime, non al lancio
iPad a schermo intero regular regular Circa 1024 pt di larghezza
iPad in Split View a metà regular regular Solo circa 507 pt di larghezza, sempre regular
iPad in Slide Over compact compact Una forma compact su iPad
Schermo esterno del Duo compact compact Circa 466 pt di larghezza
Schermo interno del Duo dispiegato regular compact Cambia in runtime con la piega

Leggi questa tabella tre volte e emergono due conclusioni contro-intuitive: «girare su un iPhone» non vuol più dire compact (una finestra ingrandita è regular), e «girare su un iPad» non vuol più dire regular (Slide Over è compact). Né il tipo di dispositivo né l'orientamento rispondono a «quale layout dovrei usare adesso». Bisogna chiedere alla classe di dimensione, in runtime.

La tabella corregge anche una vecchia credenza: ruotare il dispositivo non vuol dire «il dispositivo è cambiato». Ruotare commuta la coppia (H, V) da (compact, regular) a (compact, compact) e cambia i bound una volta. La struttura del tuo codice di layout non si muove; ciò che si muove è l'ingresso. Nell'epoca in cui l'orientamento era un concetto di layout, è stato sempre una variabile di sostituzione. Il sostituto non c'è più. Resta solo lo spazio.

Il dirupo delle classi di dimensione: perché serve un secondo passaggio

Le classi di dimensione sono binarie, e abbastanza grossolane da «mentire». Guarda il dirupo: l'iPad a schermo intero da 1024 pt e la metà in Split View da 507 pt sono entrambi (regular, regular): ma in uno entra una barra laterale, nell'altro no. Due parole non possono rispondere alle domande di grado: quante colonne, di che dimensioni, limitare la larghezza o no.

Il modo maturo è quindi una staffetta a due passaggi: le classi di dimensione rispondono alla domanda di direzione (una colonna o diviso), la strategia di ingegneria risponde alla domanda di grado (quante colonne, dimensione dell'hero, larghezza di lettura). Il secondo passaggio tipicamente scala secondo la larghezza misurata del contenitore: su schermo largo limita il testo a una lunghezza di riga comoda, o deduce il numero di colonne dalla dimensione minima dei contenuti. Da iOS 17, SwiftUI può misurare direttamente la dimensione del contenitore con onGeometryChange e inserirla nella decisione: non serve ricorrere a GeometryReader.

4. Principio tre: la funzionalità non cambia con la dimensione, cambia solo la quantità visibile

Questo è un principio delle Human Interface Guidelines facile da mancare e impossibile da sopravvalutare: quando cambia la classe di dimensione, l'insieme delle funzionalità resta identico. Ciò che cambia è «quanto se ne vede in una volta».

Su uno schermo largo la tab bar si dispiega in barra laterale e rivela le destinazioni di secondo livello. In una finestra stretta, gli strumenti a bassa priorità migrano nel menu di overflow e restano a un tocco. Nascondere è un riarrangiamento, non una cancellazione. Se un'azione esiste nel layout largo e sparisce senza traccia in quello stretto, quella non è adattamento, è una funzionalità mancante. Altrettanto, tra verticale e orizzontale non deve mai esistere «questa schermata si usa completamente solo in un orientamento»: ciò che funziona in verticale deve funzionare dalla prima all'ultima in orizzontale.

Il requisito implicito per chi progetta il prodotto: nell'architettura dell'informazione, scrivi una priorità per ogni elemento. Condivisione e azioni principali hanno priorità alta e risiedono a ogni dimensione. Salvataggio e impostazioni secondarie hanno priorità bassa: risiedono nel largo, finiscono nell'overflow nello stretto. Il meccanismo Visibility Priority dei componenti di sistema fa esattamente questo.

5. Principio quattro: le dimensioni min / max prevengono la sovrapposizione, non rifiutano il ridimensionamento

UIKit consente a una scena di dichiarare una dimensione minima e una massima. Ma la semantica va chiarita: questi due valori esistono perché gli elementi non si sovrappongano nelle dimensioni piccole e non si sfaldino in quelle grandi. Non sono una barriera che l'utente deve superare prima che gli sia concesso trascinare. Dal momento in cui una finestra può essere trascinata a qualsiasi dimensione, la tua responsabilità è mantenere il contenuto utilizzabile, leggibile e senza sovrapposizioni a qualsiasi dimensione. Se una certa dimensione si rompe inevitabilmente, allora la tua dimensione minima era troppo avida, o il layout non è ancora realmente adattivo.

Si dichiara alla connessione della scena:

func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
           options: UIScene.ConnectionOptions) {
    guard let windowScene = scene as? UIWindowScene else { return }

    // Limite inferiore: più sotto, gli elementi iniziano a sovrapporsi.
    // Limite superiore: più sopra, il layout si allenta.
    windowScene.sizeRestrictions?.minimumSize = CGSize(width: 320, height: 480)
}

Il vecchio debito che l'accompagna: UIRequiresFullScreen è deprecato, e chi lo conserva resta escluso dal ridimensionamento: abbandona automaticamente le nuove dimensioni di schermo. Dall'SDK iOS 26, le app non hanno bisogno né di cambiare codice né di risottomettersi per nuovi schermi; il sistema si adatta da solo, a patto che non serri tu stesso la porta.

6. Principio cinque: lascia che i componenti di sistema facciano il lavoro

La strategia meno costosa nell'era della resizability è affidare il riarrangiamento ai componenti di sistema. Il loro trattamento delle proporzioni arbitrarie è più robusto di qualsiasi layout scritto a mano:

  • Tab bar e barre degli strumenti: quando la finestra si allarga, le icone delle tab restano su una riga con le loro etichette e mantengono la barra compatta; quando si restringe, gli strumenti a bassa priorità defluiscono nel menu di overflow. In un'app di notizie, «Condividi» si può fissare a ogni dimensione e «Salva per dopo» trabocca solo nello stretto: dichiarato via Visibility Priority, senza una riga di codice di layout.

  • Barre laterali: da iPadOS 26, anche le app iPhone possono scegliere un layout con barra laterale quando lo spazio lo consente, protetto da sidebar.isAvailable.

  • NavigationSplitView: da iOS 26, le colonne appaiono e scompaiono secondo lo spazio; gestirne a mano la visibilità non è più necessario.

  • Materiali di sistema Liquid Glass: su iOS 27 con diffusione migliorata e separazione dei bordi; ereditati senza ricompilare.

La tua UI ha qui esattamente un compito: non litigare con questi mattoni. Le barre alte disegnate a mano devono evitare i comandi chiudi e minimizza in alto a sinistra della finestra (tramite la guida di layout con adattamento orizzontale degli angoli). Non dare mai per scontato che la tab bar sia sempre in basso né la barra degli strumenti sempre in alto: la loro stessa forma cambia con lo spazio.

7. UIKit in pratica: configurazione della scena e risposta alla geometria

Le scene sono il fondamento della resizability: ogni scena gestisce autonomamente la propria istanza di UI e di stato, e fornisce il contesto «dove e a quale dimensione sta questa UI». Da iOS 27, le build con SDK recente devono adottare il ciclo di vita UIScene: non è opzionale.

Un'intelaiatura di delegato della scena da copiare tale quale:

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession,
               options: UIScene.ConnectionOptions) {
        guard let windowScene = scene as? UIWindowScene else { return }

        // 1) Dichiarare le capacità di dimensione: prevenire la sovrapposizione, non rifiutare il ridimensionamento
        windowScene.sizeRestrictions?.minimumSize = CGSize(width: 320, height: 480)

        // 2) Appendere la finestra alla scena; mai UIWindow(frame: UIScreen.main.bounds)
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = AdaptiveRootController()
        self.window = window
        window.makeKeyAndVisible()
    }

    // 3) Callback di cambiamento della geometria: trascinare, Split View, dispiegare, schermo esterno
    func windowScene(_ windowScene: UIWindowScene,
                     didUpdateEffectiveGeometry previous: UIWindowScene.Geometry) {
        let geometry = windowScene.effectiveGeometry
        let size = geometry.coordinateSpace.bounds.size

        // isInteractivelyResizing significa che l'utente tiene ancora il bordo.
        // Il lavoro pesante (ricostruzione delle risorse, ricalcolo dei grafici)
        // si fa una volta, quando il gesto finisce: non per ogni dimensione intermedia.
        if !geometry.isInteractivelyResizing,
           size != previous.coordinateSpace.bounds.size {
            AssetStore.shared.rebuild(for: size)
        }
    }

    // 4) Preferenza di stile dei comandi della finestra (chiudi / minimizza), iPadOS 26+
    func preferredWindowingControlStyle(for scene: UIWindowScene)
        -> UIWindowScene.WindowingControlStyle {
        .unified
    }
}

Tre punti meritano di essere spiegati:

isInteractivelyResizing è la tavola di salvezza delle prestazioni nel trascinamento. Mentre l'utente trascina, il sistema riporta la geometria in continuo. Se un gioco o un'app ricostruisce le risorse di rendering per ogni dimensione intermedia, il frame rate crolla sul posto. La postura standard: mentre si trascina, solo il leggero (vincoli, dimensioni dei font); dopo il rilascio, una sola volta il pesante.

Non prendere mai schermo e dimensione tramite UIScreen.main. Nel mirroring e su schermo esterno, lo schermo principale è la risposta sbagliata. Le fonti corrette sono view.window?.windowScene?.screen, l'effectiveGeometry della scena, o i view.bounds locali della vista.

Evitare i comandi della finestra. Da iPadOS 26, l'angolo in alto a sinistra della scena porta i comandi chiudi e minimizza. Le barre alte disegnate a mano devono legarsi a containerView.layoutGuide(for: .margins(cornerAdaptation: .horizontal)), o il tuo primo bottone diventa intoccabile.

8. Lo strato delle viste: cancellare tre vecchi modi

Il codice UIKit adattivo è, in fondo, «tre sostituzioni»:

Cancellare Sostituire con Perché
UIScreen.main.bounds view.bounds / effectiveGeometry / windowScene?.screen In Split View e mirroring, lo schermo principale non è la tua finestra
I rami userInterfaceIdiom == .pad traitCollection.horizontalSizeClass Il tipo di dispositivo non porta semantica di layout
I rami interfaceOrientation Classe di dimensione + bound locali L'orientamento è un risultato del layout, non la sua causa

Dopo lo scambio, il cambiamento di trait pilota il layout:

class AdaptiveRootController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Riarrangiare al cambio di classe di dimensione; la registrazione copre
        // anche l'invalidazione della cache che il tracking automatico non vede
        registerForTraitChanges([UITraitHorizontalSizeClass.self,
                                 UITraitVerticalSizeClass.self]) { (vc: Self, _) in
            vc.applyLayout()
        }
    }

    private func applyLayout() {
        switch (traitCollection.horizontalSizeClass, traitCollection.verticalSizeClass) {
        case (.regular, _):   useSidebarLayout()
        case (.compact, _):   useStackedLayout()
        default:              useStackedLayout()
        }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        // Quando il giudizio è più fine di una classe di dimensione: dimensione locale disponibile
        fineTune(for: view.bounds.size)
    }
}

Nota che viewDidLayoutSubviews / layoutSubviews agiscono in continuo: il cambio di classe di dimensione innesca il «riarrangiamento strutturale», il cambio di bound innesca la «messa a punto fine». Leggere la dimensione una sola volta in onAppear / viewDidLoad e conservarla produce i primi valori stantii appena inizia il ridimensionamento.

9. SwiftUI in pratica: ampiamente automatico, rinforzato nei punti chiave

Le app scritte in SwiftUI partono avvantaggiate sulla resizability: ricompilate con Xcode 27, il supporto al ridimensionamento arriva da sé, non c'è una nuova API da adottare, e i nuovi materiali Liquid Glass sono ereditati di passaggio. Ma «automatico» non vuol dire «senza ispezione». La cassetta degli attrezzi lato SwiftUI:

  • @Environment(\.horizontalSizeClass) / verticalSizeClass: l'equivalente del trait UIKit, risponde alle domande di direzione.

  • onGeometryChange(for:of:action:): misura il contenitore, risponde alle domande di grado. Legge senza innescare la presa di spazio avida di GeometryReader, e chiama l'azione solo quando il valore derivato cambia davvero: un filtro naturale per le dimensioni intermedie del trascinamento.

  • ViewThatFits: il dichiarativo «prendi il primo che ci sta», adatto quando il contenuto cambia disposizione secondo la larghezza.

  • containerRelativeFrame(): dimensiona secondo la proporzione del contenitore anziché in punti assoluti; particolarmente utile per le zone che devono estendersi sotto l'UI di sistema.

  • NavigationSplitView: da iOS 26, larghezza e visibilità delle colonne si adattano da sole; non avvolgere sopra una gestione manuale delle colonne.

  • .windowResizability(.contentMinSize): l'ingresso SwiftUI per dichiarare la dimensione minima della scena, controparte di sizeRestrictions?.minimumSize.

Una staffetta a due passaggi tipica:

struct DashboardView: View {
    @Environment(\.horizontalSizeClass) private var hSize
    @State private var columnCount = 1

    var body: some View {
        ScrollView {
            MetricGrid(columns: columnCount)
        }
        // Passaggio uno: la classe di dimensione decide una colonna o diviso
        .onChange(of: hSize) { _, new in
            usesSidebar = (new == .regular)
        }
        // Passaggio due: la larghezza misurata decide il numero di colonne,
        // coprendo 507 e 1024 che sono entrambi "regular"
        .onGeometryChange(for: CGFloat.self) { $0.size.width } action: { _, width in
            columnCount = AdaptiveWindowLayoutPolicy.tier(for: width).columns
        }
    }
}

10. Linee rosse in Info.plist e Launch Screen

Due linee rosse vivono nella configurazione del progetto. Sbagliane una e detona al momento della sottomissione:

  1. UIRequiresFullScreen va trattato. Deprecato, e chi lo conserva resta escluso dal ridimensionamento. Cancellalo; se porta una vera esigenza di compatibilità con il passato, usa UIRequiresFullScreenIgnoredStartingWithVersion per dichiarare da quale versione la chiave viene ignorata. I giochi entrano per questo nel ridimensionamento discreto: dopo ogni trascinamento concluso, commutano su una nuova configurazione di schermo assortita alla dimensione, il che preserva il rendering a piena qualità.

  2. Il Launch Screen è obbligatorio. Dall'SDK iOS 27, un'app senza Launch Screen configurato non può passare la sottomissione all'App Store (TN3208). In un progetto SwiftUI questo di solito significa aggiungere una configurazione minima di schermata di lancio: non continuare a correre scalzo.

11. Riferimento rapido degli anti-pattern

Prima di toccare il codice, passa il codice al setaccio di questi pattern. Ogni occorrenza è un debito da pagare:

Anti-pattern Perché si rompe Sostituire con
UIScreen.main.bounds In Split View / mirroring, non è la tua finestra view.bounds locali o geometria della scena
I rami UIDevice.current.userInterfaceIdiom Il tipo di dispositivo non ha semantica di layout horizontalSizeClass
interfaceOrientation / notifiche di orientamento Riportano la postura del dispositivo, non la forma della finestra Classe di dimensione + bound locali
Soglie fatte in casa tipo size.width > 600 Bypassano la semantica dei trait, mancano gli stati intermedi di Split View Strategia di scala di ingegneria + onGeometryChange
Leggere la dimensione una volta in onAppear Il ridimensionamento è continuo; la cache invecchia subito Callback di trait / geometria
Layout largo solo per l'iPad Un iPad in Slide Over si comporta come un telefono Logica larga e logica stretta entrambe innescate dallo spazio
.frame(height: 480) fisso per mappe / hero Nelle finestre corte, il testo scivola fuori dalla prima schermata Altezza relativa al contenitore o adattiva

12. Roadmap di migrazione

Quattro passi, ordinati per rischio e rendimento:

Fase 1 · Disinnescare (per prima, blocca la sottomissione): cancellare UIRequiresFullScreen, aggiungere il Launch Screen, confermare che il ciclo di vita UIScene è in uso. Questi tre punti sono porte dure, senza relazione con la qualità del progetto; saltarne uno inceppa direttamente la build o la revisione.

Fase 2 · Ripulire gli anti-pattern: con la tabella della sezione 11, sostituire in tutta la base UIScreen.main, i rami idiom / orientamento e le soglie di larghezza fatte in casa. L'obiettivo non è «gira»: è unificare l'ingresso del layout sulla semantica dello spazio.

Fase 3 · Costruire le due passate: per le schermate guidate dal contenuto, stabilire la strategia «la classe di dimensione decide la direzione + la larghezza misurata decide il grado», e far convergere ogni soglia nuda in quel punto unico. Su schermo largo, limitare la larghezza del testo: una riga oltre 85 caratteri è un bug di leggibilità.

Fase 4 · Sistematizzare i test: percorrere la matrice della sezione 13 dimensione per dimensione, poi congelare i risultati come punti di non regressione.

13. Matrice di test

I test di resizability non si organizzano per elenchi di dispositivi, ma per forme di spazio. Ogni forma deve rispondere: la funzionalità è completa, il contenuto è tagliato, il chrome è toccabile?

Forma di spazio Cosa verificare
Larghezza utilizzabile più stretta (vicino a minimumSize) Sovrapposizione degli elementi, bottoni principali toccabili
Larghezza telefono standard Linea di base del layout predefinito
Telefono in orizzontale In vertical compact: tab bar in verticale, prima schermata completa
Finestra telefono ingrandita fino a regular Le colonne subentrano, lo stato si conserva
Split View a metà / Slide Over Due comportamenti di spazio sullo stesso iPad
Rapporto estremo largo-piatto e alto-stretto L'estensione dello sfondo regge, il contenuto non si squarcia
Duo esterno e interno dispiegato Layout e stato continui al cambio di piega
Mirroring iPhone / schermo esterno Le interrogazioni di schermo e dimensione sono corrette

Dal lato strumenti, il Device Hub e le Preview di Xcode 27 offrono una modalità di ridimensionamento della finestra; tirare il bordo cambia la dimensione in continuo. Mirroring e schermi esterni si verificano su hardware reale.

14. Domande frequenti

Perché la mia app iPhone può improvvisamente essere trascinata a una finestra più grande?

Non è un bug: comportamento nuovo dall'SDK iOS 26. Le app iPhone che girano su iPad e nel mirroring iPhone su Mac hanno finestre liberamente ridimensionabili. Il segnale di layout corrispondente è la classe di dimensione orizzontale che commuta da compact a regular. Il vecchio codice if idiom == .phone produce il layout sbagliato in tali finestre: chiedi alla classe di dimensione.

Basta le classi di dimensione? Perché misurare anche la larghezza?

Non bastano, e il dirupo è reale. L'iPad a schermo intero e la metà in Split View sono entrambi (regular, regular), ma le loro larghezze differiscono di un fattore due: in uno entra una barra laterale, nell'altro no. Le classi di dimensione decidono la direzione (una colonna o diviso), la larghezza misurata decide il grado (quante colonne, di che dimensioni). Le due sono una staffetta, non una scelta.

Se dichiaro minimumSize, gli utenti non possono più trascinare più piccolo?

minimumSize è il limite sotto il quale il tuo contenuto inizierebbe a ingarbugliarsi; gli utenti non possono trascinare oltre. È un meccanismo di prevenzione della sovrapposizione, non un portale di funzionalità contro il ridimensionamento. Ciò che devi è l'usabilità a ogni dimensione tra minimumSize e maximumSize. Se una dimensione fallisce, l'adattamento è incompiuto: non è una ragione per alzare il minimo.

Cosa succede se cancello UIRequiresFullScreen?

L'app entra nel ridimensionamento delle finestre, l'atteso predefinito da iOS 26+. Per la compatibilità con il passato puoi usare UIRequiresFullScreenIgnoredStartingWithVersion per dichiarare la versione da cui ignorare; i giochi entrano nel ridimensionamento discreto e commutano dopo ogni trascinamento su una configurazione di schermo assortita, il che preserva meglio la qualità di rendering.

Cosa deve fare realmente un'app SwiftUI?

Ricompilare, e il supporto al ridimensionamento è lì; nessuna nuova API da adottare. Ispeziona invece: il codice che si appoggia a ipotesi dell'era di UIScreen; i giudizi di dimensione che usano solo le classi di dimensione senza rinforzo di misura; i componenti a frame fisso che si squarciano nelle proporzioni estreme. Il framework si occupa del macro. Il componente che si squarcia è di solito quello che hai inchiodato tu stesso.

Fonti e letture di approfondimento

Fonti ufficiali: la sessione WWDC25 282 «Make your UIKit app more flexible», la sessione WWDC26 278 «Modernize your UIKit app», le sezioni Layout e Designing for iPhone Duo delle Human Interface Guidelines, la documentazione di UISceneSizeRestrictions e UIWindowScene.Geometry, e le note tecniche TN3192: migrazione dalla chiave UIRequiresFullScreen deprecata e TN3208: requisiti del Launch Screen.

Approfondimenti su questo sito: per vedere lo stesso pensiero atterrare dalla prima all'ultima su un dispositivo concreto, leggi Progettare per iPhone Duo, dal layout al codice. Per l'altra faccia: anche i dati devono contrarsi con lo spazio, vedi la guida alla linea di base personale. Le altre domande di prodotto e adattamento sono nelle domande frequenti.

Continua a leggere

Prova queste idee in Stress HRV

Scarica dall'App Store

Queste note condividono pensiero di prodotto per il benessere. Non sono consiglio medico.