iOS-Resizability: wenn eine App nicht mehr weiß, auf welchem Gerät sie läuft

Fünf Designprinzipien, jedes in Code umgesetzt: Im Zeitalter der Fensterskalierung kümmert eine App nur, wie viel Platz sie hat. Mit Szenenkonfiguration, Geometrie-Callbacks, Zwei-Stufen-Strategie, Info.plist-Rotlinien und Testmatrix.

Resizability bedeutet: Das Fenster einer App lässt sich wie ein Desktop-Fenster am Rand greifen, frei ziehen und in der Größe verändern. Der Designgedanke, den Apple zu dieser Veränderung mitgibt, passt in einen Satz – eine App kümmert sich nicht mehr darum, auf welchem Gerät, in welcher Ausrichtung und auf welchem Bildschirm sie läuft. Sie kümmert sich nur darum, wie viel Platz sie gerade hat. Du definierst zwei Verhaltensweisen: wie Inhalte stehen, wenn der Platz groß ist, und wie, wenn er klein ist. Das System trägt diese Logik über alle Geräte, alle Fenstergrößen und alle Klappzustände.

Das ist keine normale API-Aktualisierung. Es ist ein Spurwechsel im Layout-Paradigma seit Bestehen von iOS. Dieser Artikel zerlegt den Designgedanken in fünf Prinzipien, setzt jedes einzelne in UIKit- und SwiftUI-Code um und endet mit einer Migrations-Roadmap und einer Testmatrix, die du direkt abarbeiten kannst.

Die Signaturen im Text sind gegen das iOS 27.1 SDK aus Xcode 27.1 abgeglichen. Das Verhalten folgt Apples Dokumentation und den WWDC-Sessions, die Quellen stehen am Ende. Der Fließtext ist eine Nacherzählung und eine technische Aufbereitung, keine Übersetzung einer bestimmten Seite.

1. Von iOS 26 zu 27: wie das Skalieren zum Standard wurde

Vor dem Designgedanken die Zeitleiste. Sie erklärt, warum die alte Vorgehensweise nicht mehr ausreicht.

Phase Was passiert ist Was es für dich bedeutet
iPadOS 15 Split View / Slide Over / Stage Manager iPad bekommt Größen jenseits von Vollbild
iPadOS 26 iPad im Zeitalter freier Fenster, beliebig ziehen und skalieren Die Annahme „iPad = regular" gerät ins Wanken
iOS 26 SDK UIRequiresFullScreen ist veraltet Kein Ausstieg aus der Skalierung über die Vollbild-Taste
iOS 26 SDK iPhone-Apps skalieren auch auf iPad und in Mac-Spiegelung „Läuft auf einem iPhone" heißt nicht mehr compact
iOS 27 UIScene-Lebenszyklus ist Pflicht für Builds mit aktuellem SDK Szenen werden das Fundament
iOS 27 Systemkomponenten wie Tab-Bar und Toolbars passen sich an jedes Seitenverhältnis an Systembausteine übernehmen die Hauptarbeit

Der Bogen in einem Satz: Die Fenstergröße wurde von einem Aufzählungswert zu einem stetigen Wert. Früher sah eine App 375, 393, 414, 768, 1024. Jetzt greift ein Finger an den Fensterrand und zieht einmal: Die Breite kann jede Zahl zwischen 320 und der Bildschirmgrenze sein. Layout, das für diskrete Stufen festgeschrieben wurde, bricht am stetigen Wert garantiert.

2. Prinzip eins: vom „Gerätedenken" zum „Raumdenken"

Fast alles alte Layout-Wissen steht auf Gerätedenken: Das ist ein iPhone, es ist quer, also so anordnen; das ist ein iPad, also in zwei Spalten. Resizability verlangt, dieses Denken vollständig zu tauschen.

Gerätedenken (alt) Raumdenken (neu)
Entscheidungsgrund Gerätetyp, Ausrichtung, Bildschirmgröße Verfügbarer Raum des aktuellen Containers
Layout-Anzahl Ein Version pro Gerät Ein Regelsatz für alle Räume
Neue Hardware Vielleicht Codeänderungen und ein Release Greift automatisch, null Änderungen
Klappzustände Pro Haltung ein weiteres Interface Ein Interface, das mit der Breite mitwächst
Code-Geruch if idiom == .pad, isLandscape horizontalSizeClass, Containerbreite

Die schlichteste Formulierung des Raumdenkens kommt von der WWDC: Du entwirfst nicht für jede Plattform und jede Fenstergröße einzeln. Du definierst einmal, wie Inhalte sich verhalten, wenn mehr Platz da ist und wenn weniger da ist. Das System trägt diese Logik auf jedes Seitenverhältnis. Das Drehen des Geräts ist nur ein Auslöser dieser Logik, dem Ziehen eines Fensters, dem Wechsel in Split View oder dem Aufklappen dem Wesen nach gleichartig – am Ende läuft alles auf denselben einen Punkt zu: Der verfügbare Raum hat sich verändert.

3. Prinzip zwei: Size Classes sind die neue Lingua franca

Wenn das Gerätedenken abtritt, übernimmt was den Stab? Die Size Class. Sie ist die qualitative Beurteilung des Raums durch das Framework: zwei Achsen, je zwei Wörter – compact heißt beengt, regular heißt geräumig.

  • Die horizontale Achse urteilt über links und rechts: Bei compact gehört der Inhalt in eine Spalte gestapelt; erst bei regular sind Spalten, Reihung und Sidebar ehrlich.

  • Die vertikale Achse urteilt über oben und unten: Bei compact passt das vertikale Chrome (Tab-Bar, Toolbar) nicht mehr hin, und das System stellt eine waagerechte Tab-Bar auf die schmale Kante. Bei regular halten obere und untere Leisten gleichzeitig stand.

In SwiftUI ausgelesen:

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

if hSize == .regular {
    // Links und rechts Platz: Spalten / Sidebar / zweireihig
} else {
    // Links und rechts beengt: eine Spalte, gestapelt
}

In UIKit trägt traitCollection.horizontalSizeClass dieselbe Pflicht, und mit registerForTraitChanges lassen sich Änderungen gezielt abonnieren.

Es folgt die wichtigste Tabelle dieses Textes – Size Classes stehen in keiner Eins-zu-eins-Beziehung zu Gerät und Ausrichtung:

Szene Horizontal Vertikal Anmerkung
iPhone hochkant compact regular Die Standardform der ganzen App
iPhone quer compact compact Nur noch etwa 320pt hoch, Tab-Bar steht hochkant
iPhone-Fenster vergrößert (iOS 26+) regular regular Ändert sich zur Laufzeit, nicht beim Start
iPad Vollbild regular regular Etwa 1024pt breit
iPad Split View halb regular regular Nur etwa 507pt breit, immer noch regular
iPad Slide Over compact compact Eine compact-Form auf dem iPad
Duo Außendisplay compact compact Etwa 466pt breit
Duo aufgeklapptes Innendisplay regular compact Wechselt mit dem Klappzustand zur Laufzeit

Lies diese Tabelle dreimal, und zwei gegen die Intuition stehende Schlussfolgerungen treten heraus: „Läuft auf einem iPhone" heißt nicht mehr compact (ein vergrößertes Fenster ist regular), und „läuft auf einem iPad" heißt nicht mehr regular (Slide Over ist compact). Weder Gerätetyp noch Ausrichtung beantworten „welches Layout soll ich jetzt benutzen". Man fragt die Size Class zur Laufzeit.

Die Tabelle korrigiert auch einen alten Glauben: Das Gerät drehen heißt nicht „das Gerät hat sich verändert". Drehen schaltet das Paar (H, V) von (compact, regular) auf (compact, compact) um und verändert einmal die Bounds. Die Struktur deines Layout-Codes bewegt sich nicht, bewegt wird nur die Eingabe. In der Zeit, in der „Ausrichtung" ein Layout-Begriff war, war sie immer eine Ersatzvariable. Der Ersatz ist weg. Es bleibt nur der Raum.

Die Size-Class-Klippe: warum eine zweite Stufe nötig ist

Size Classes sind binär und grob genug, um zu „lügen". Sieh die Klippe: iPad-Vollbild mit 1024pt und Split View halb mit 507pt sind beide (regular, regular) – aber in das eine passt eine Sidebar, in das andere nicht. Zwei Wörter können die Grad-Fragen nicht beantworten: wie viele Spalten, wie groß, Breite begrenzen oder nicht.

Die erwachsene Vorgehensweise ist deshalb ein Staffellauf über zwei Stufen: Size Classes beantworten die Richtungsfrage (eine Spalte oder geteilt), die Ingenieursstrategie beantwortet die Grad-Frage (wie viele Spalten, Hero-Größe, Lesebreite). Die zweite Stufe stafft typischerweise nach gemessener Containerbreite: Auf breiten Bildschirmen begrenzt sie den Text auf eine angenehme Zeilenlänge, oder sie leitet die Spaltenzahl aus der Mindestgröße der Inhalte ab. Seit iOS 17 kann SwiftUI mit onGeometryChange die Containergröße direkt messen und in diese Entscheidung einspeisen – auf GeometryReader brauchst du nicht zurückzugreifen.

4. Prinzip drei: Die Funktion ändert sich mit der Größe nicht, nur die sichtbare Menge

Das ist ein leicht zu übersehender, aber nicht hoch genug zu schätzender Grundsatz der Human Interface Guidelines: Wenn sich die Size Class ändert, bleibt die Funktionsmenge gleich. Es ändert sich nur „wie viel man auf einmal sieht".

Auf einem breiten Bildschirm klappt die Tab-Bar zur Sidebar auf und zeigt Sekundärziele. In einem schmalen Fenster wandern Werkzeuge niedriger Priorität ins Overflow-Menü und bleiben mit einem Tipp erreichbar. Verstecken ist Umgruppieren, nicht Löschen. Wenn eine Aktion im breiten Layout existiert und im schmalen spurlos verschwindet, ist das keine Anpassung, sondern ein fehlendes Feature. Ebenso darf es zwischen Hoch- und Querformat nicht geben „dieser Screen lässt sich nur in einer Ausrichtung komplett bedienen" – was hochkant geht, muss auch quer von vorne bis hinten aufgehen.

Die stille Anforderung an die Produktgestaltung lautet: Schreibe in der Informationsarchitektur jeder Einheit eine Priorität zu. Teilen und Primäraktionen haben hohe Priorität und sind in jeder Größe resident. Speichern und Sekundäres haben niedrige Priorität: breit resident, schmal im Overflow. Der Visibility Priority-Mechanismus der Systemkomponenten tut genau dies.

5. Prinzip vier: Min-/Max-Größen verhindern Überlappung, sie verwehren die Skalierung nicht

UIKit erlaubt es einer Szene, eine minimale und eine maximale Größe zu deklarieren. Die Semantik muss aber klar sein: Diese beiden Werte existieren, damit Elemente in kleinen Größen einander nicht überdecken und in großen nicht ausfasern. Sie sind keine Hürde, die der Nutzer nehmen muss, bevor ihm das Ziehen erlaubt wird. Sobald ein Fenster auf jede Größe gezogen werden kann, ist es deine Verantwortung, Inhalte in jeder Größe mindestens benutzbar, lesbar und überlappungsfrei zu halten. Bricht eine bestimmte Größe unvermeidlich, dann war deine Minimalgröße zu gierig – oder das Layout ist noch nicht wirklich adaptiv.

Deklariert beim Verbinden der Szene:

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

    // Untergrenze: darunter beginnen sich Elemente zu überdecken.
    // Obergrenze: darüber wird das Layout schlaff.
    windowScene.sizeRestrictions?.minimumSize = CGSize(width: 320, height: 480)
}

Die alte Rechnung, die dazugehört: UIRequiresFullScreen ist veraltet, und wer es hält, bleibt von der Skalierung ausgeschlossen – gibt neue Displaygrößen automatisch preis. Seit dem iOS 26 SDK brauchen Apps für neue Bildschirme weder Codeänderungen noch eine erneute Einreichung; das System passt automatisch an – sofern du die Tür nicht selbst verriegelst.

6. Prinzip fünf: Lass die Systemkomponenten die Arbeit machen

Die sparsamste Strategie im Zeitalter der Resizability ist, das Umgruppieren an Systemkomponenten abzugeben. Ihr Umgang mit beliebigen Seitenverhältnissen ist robuster als jedes handgeschriebene Layout:

  • Tab-Bars und Toolbars: Wird das Fenster breiter, bleiben Tab-Icons in einer Zeile mit ihren Labels und halten die Bar kompakt. Wird es schmaler, wandern Werkzeuge niedriger Priorität ins Overflow-Menü. In einer News-App lässt sich „Teilen" über alle Größen anpinnen und „Später lesen" erst im Schmalen überlaufen – über Visibility Priority deklariert, ohne eine Zeile Layout-Code.

  • Sidebars: Seit iPadOS 26 können auch iPhone-Apps ein Sidebar-Layout wählen, wenn der Platz es erlaubt; abgesichert über sidebar.isAvailable.

  • NavigationSplitView: Seit iOS 26 zeigen und verbergen sich Spalten nach Platz; Spaltensichtbarkeit von Hand zu verwalten ist nicht mehr nötig.

  • Liquid-Glass-Systemmaterialien: Auf iOS 27 mit verbesserter Diffusion und Kantentrennung; ohne Neukompilierung geerbt.

Deine eigene UI hat hier genau eine Aufgabe: Mit diesen Bausteinen nicht zu kämpfen. Selbstgezeichnete Top-Bars müssen die Schließen- und Minimieren-Steuerung oben links meiden (über den Layout-Guide mit horizontaler Corner-Adaption). Nimm nie an, die Tab-Bar sei immer unten und die Toolbar immer oben – ihre Gestalt selbst verändert sich mit dem Raum.

7. UIKit in der Praxis: Szenenkonfiguration und Geometrie-Antwort

Szenen sind das Fundament der Resizability: Jede Szene verwaltet ihre eigene Instanz von UI und Zustand eigenständig und liefert den Kontext „wo und wie groß steht dieses UI". Seit iOS 27 müssen Builds mit aktuellem SDK den UIScene-Lebenszyklus übernehmen – das ist nicht optional.

Ein Scene-Delegate-Gerüst zum direkten Abschreiben:

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) Größenfähigkeit deklarieren: Überlappung verhindern, Skalierung nicht verwehren
        windowScene.sizeRestrictions?.minimumSize = CGSize(width: 320, height: 480)

        // 2) Fenster an die Szene hängen; nie UIWindow(frame: UIScreen.main.bounds)
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = AdaptiveRootController()
        self.window = window
        window.makeKeyAndVisible()
    }

    // 3) Geometrie-Rückruf: Ziehen, Split View, Aufklappen, externer Displaywechsel
    func windowScene(_ windowScene: UIWindowScene,
                     didUpdateEffectiveGeometry previous: UIWindowScene.Geometry) {
        let geometry = windowScene.effectiveGeometry
        let size = geometry.coordinateSpace.bounds.size

        // isInteractivelyResizing bedeutet: der Nutzer hält den Rand noch.
        // Schwere Arbeit (Asset-Neuaufbau, Chart-Neurechnung) passiert einmal,
        // wenn die Geste endet – nicht für jede Zwischengröße.
        if !geometry.isInteractivelyResizing,
           size != previous.coordinateSpace.bounds.size {
            AssetStore.shared.rebuild(for: size)
        }
    }

    // 4) iPadOS 26+ Stil der Fenstersteuerung (Schließen / Minimieren)
    func preferredWindowingControlStyle(for scene: UIWindowScene)
        -> UIWindowScene.WindowingControlStyle {
        .unified
    }
}

Drei Punkte verdienen Entfaltung:

isInteractivelyResizing ist die Lebensader der Zieh-Performance. Während des Ziehens meldet das System Geometrie fortlaufend. Baut ein Spiel oder eine App für jede Zwischengröße Renderressourcen neu auf, bricht die Bildrate auf der Stelle ein. Die Standardhaltung: beim Ziehen nur Leichtes aktualisieren (Constraints, Schriftgrößen), nach dem Loslassen einmal das Schwere.

Nimm Bildschirm und Größe nie über UIScreen.main. Unter Spiegelung und externen Displays ist der Hauptbildschirm die falsche Antwort. Richtige Quellen sind view.window?.windowScene?.screen, die effectiveGeometry der Szene oder die lokalen view.bounds.

Fenstersteuerung meiden. Seit iPadOS 26 trägt die Szene oben links Steuerungen zum Schließen und Minimieren. Selbstgezeichnete Top-Bars müssen sich an containerView.layoutGuide(for: .margins(cornerAdaptation: .horizontal)) binden, sonst wird dein erster Button untippbar.

8. Die View-Schicht: drei alte Muster streichen

Adaptiver UIKit-View-Code ist im Kern „drei Ersetzungen":

Streichen Ersetzen durch Warum
UIScreen.main.bounds view.bounds / effectiveGeometry / windowScene?.screen Unter Split View und Spiegelung ist der Hauptbildschirm nicht dein Fenster
userInterfaceIdiom == .pad-Zweige traitCollection.horizontalSizeClass Der Gerätetyp trägt keine Layout-Semantik
interfaceOrientation-Zweige Size Class + lokale Bounds Ausrichtung ist ein Ergebnis des Layouts, nicht seine Ursache

Nach dem Tausch treibt die Trait-Änderung das Layout:

class AdaptiveRootController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Bei Size-Class-Wechsel umgruppieren; Registrierung deckt auch
        // Cache-Ungültigkeit ab, die automatisches Tracking nicht sieht
        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()
        // Wenn das Urteil feiner ist als eine Size Class: lokale verfügbare Größe
        fineTune(for: view.bounds.size)
    }
}

Beachte, dass viewDidLayoutSubviews / layoutSubviews fortlaufend wirken: Die Size-Class-Änderung löst die „Struktur-Umgruppierung" aus, die Bounds-Änderung die „Feinjustierung". Wer in onAppear / viewDidLoad einmal die Größe liest und behält, produziert die ersten veralteten Werte, sobald die Skalierung beginnt.

9. SwiftUI in der Praxis: überwiegend automatisch, an Schlüsselstellen unterfüttert

SwiftUI-Apps haben bei Resizability Vorsprung: Mit Xcode 27 neu kompiliert, kommt die Fenster-Skalierung automatisch, es gibt keine neue API zu übernehmen, und die neuen Liquid-Glass-Materialien werden mitgeerbt. Aber „automatisch" ist nicht „prüffrei". Der Werkzeugkasten auf SwiftUI-Seite:

  • @Environment(\.horizontalSizeClass) / verticalSizeClass: Entspricht dem UIKit-Trait, beantwortet die Richtungsfrage.

  • onGeometryChange(for:of:action:): Misst den Container, beantwortet die Grad-Frage. Es liest, ohne GeometryReaders gierigen Platzgriff auszulösen, und ruft die Aktion nur auf, wenn sich der abgeleitete Wert wirklich ändert – ein natürlicher Filter für Zwischenzustände beim Ziehen.

  • ViewThatFits: Das deklarative „nimm das erste, das passt", geeignet wenn Inhalte nach Breite die Anordnung wechseln.

  • containerRelativeFrame(): Bemisst nach Container-Verhältnis statt absoluten Punkten; besonders nützlich für Flächen, die sich unter System-UI erstrecken sollen.

  • NavigationSplitView: Seit iOS 26 passen sich Spaltenbreite und Spaltensichtbarkeit von selbst an; wickle nicht noch eine Handverwaltung darum.

  • .windowResizability(.contentMinSize): SwiftUIs Eingang für die minimale Szenengröße, das Gegenstück zu sizeRestrictions?.minimumSize.

Ein typischer Staffellauf über zwei Stufen:

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

    var body: some View {
        ScrollView {
            MetricGrid(columns: columnCount)
        }
        // Stufe eins: Size Class entscheidet einspaltig oder geteilt
        .onChange(of: hSize) { _, new in
            usesSidebar = (new == .regular)
        }
        // Stufe zwei: gemessene Breite entscheidet die Spaltenzahl,
        // deckt 507 und 1024 ab, die beide "regular" sind
        .onGeometryChange(for: CGFloat.self) { $0.size.width } action: { _, width in
            columnCount = AdaptiveWindowLayoutPolicy.tier(for: width).columns
        }
    }
}

10. Rote Linien in Info.plist und Launch Screen

Zwei rote Linien liegen in der Projektkonfiguration. Wer eine verfehlt, detoniert erst zur Einreichung:

  1. UIRequiresFullScreen muss behandelt werden. Veraltet, und wer es hält, bleibt von der Skalierung ausgeschlossen. Löschen; wenn es echte Legacy-Kompatibilität braucht, mit UIRequiresFullScreenIgnoredStartingWithVersion erklären, ab welcher Version der Schlüssel ignoriert wird. Spiele geraten dadurch in diskretes Skalieren – nach jedem abgeschlossenen Ziehen wechseln sie in eine zum Maß passende neue Bildschirmkonfiguration und halten Full-Quality-Rendering.

  2. Launch Screen ist Pflicht. Seit dem iOS 27 SDK können Apps ohne konfigurierten Launch Screen die App-Store-Einreichung nicht bestehen (TN3208). In einem SwiftUI-Projekt heißt das meist, eine minimale Startbild-Konfiguration nachzureichen – nicht weiter barfuß zu laufen.

11. Anti-Pattern-Schnellreferenz

Bevor du Code anfasst, durchsuche die Codebasis nach diesen Mustern. Jeder Treffer ist zurückzuzahlende Schuld:

Anti-Pattern Warum es bricht Ersetzen durch
UIScreen.main.bounds Unter Split View / Spiegelung nicht dein Fenster Lokale view.bounds oder Szenengeometrie
UIDevice.current.userInterfaceIdiom-Zweige Gerätetyp hat keine Layout-Semantik horizontalSizeClass
interfaceOrientation / Ausrichtungs-Notifications Meldet Gerätehaltung, nicht Fensterform Size Class + lokale Bounds
size.width > 600 selbstgebaute Breakpoints Umgeht Trait-Semantik, verfehlt Split-Zwischenzustände Ingenieur-Staffelungsstrategie + onGeometryChange
Größe einmal in onAppear lesen Skalierung ist fortlaufend, der Cache veraltet sofort Trait- / Geometrie-Rückrufe
Breites Layout nur fürs iPad Ein iPad in Slide Over benimmt sich wie ein Telefon Breite und schmale Logik beide vom Raum ausgelöst
.frame(height: 480) fest für Karten / Hero In kurzen Fenstern rutscht der Text aus dem ersten Screen Höhe container-relativ oder adaptiv

12. Migrations-Roadmap

Vier Schritte, geordnet nach Risiko und Ertrag:

Phase 1 · Entschärfen (zuerst, blockiert die Einreichung): UIRequiresFullScreen löschen, Launch Screen nachreichen, bestätigen, dass der UIScene-Lebenszyklus in Benutzung ist. Diese drei Punkte sind harte Tore, unabhängig von Entwurfsqualität; fehlen sie, klemmt Build oder Review direkt.

Phase 2 · Anti-Patterns räumen: Mit der Tabelle aus Abschnitt 11 UIScreen.main, Idiom-/Ausrichtungs-Zweige und handgemachte Breiten-Breakpoints codebasisweit ersetzen. Das Ziel ist nicht „es läuft", sondern die Layout-Eingabe auf Raumsemantik zu vereinheitlichen.

Phase 3 · Die zwei Stufen bauen: Für inhaltsgetriebene Screens die Strategie „Size Class entscheidet Richtung + gemessene Breite entscheidet Grad" etablieren und jede nackte Schwelle dort zusammenführen. Auf breiten Bildschirmen die Textbreite begrenzen; eine Zeile über 85 Zeichen ist ein Lesbarkeitsbug.

Phase 4 · Testen systematisieren: Die Matrix aus Abschnitt 13 Größe für Größe durchgehen und die Ergebnisse als Regressionspunkte einfrieren.

13. Testmatrix

Resizability-Tests werden nicht nach Gerätelisten gemacht, sondern nach Raumformen. Jede Form muss beantworten: Ist die Funktion vollständig, wird Inhalt beschnitten, ist Chrome tippbar?

Raumform Was zu prüfen ist
Schmalste nutzbare Breite (nahe minimumSize) Überlappen Elemente, sind primäre Buttons tippbar
Standard-Telefonbreite Grundlinie des Standardlayouts
Telefon quer Unter vertical compact: Tab-Bar hochkant, erster Screen vollständig
Telefonfenster bis regular vergrößert Übernehmen Spalten, bleibt Zustand erhalten
Split View halb / Slide Over Zwei Raumverhalten auf demselben iPad
Extrem breit-flache und hoch-schmale Verhältnisse Trägt die Hintergrund-Erstreckung, reißt der Inhalt nicht
Duo außen und aufgeklappt Verlaufen Layout und Zustand beim Klappen stetig
iPhone-Spiegelung / externes Display Stimmen Bildschirm- und Größenabfragen

Werkzeugseitig bieten Xcodes Device Hub und Previews einen Fenster-Resize-Modus; ein Zug am Rand ändert die Größe fortlaufend. Spiegelung und externe Displays gehören auf echte Hardware.

14. Häufige Fragen

Warum lässt sich meine iPhone-App plötzlich auf Fenstergröße ziehen?

Kein Fehler – neues Verhalten seit dem iOS 26 SDK: iPhone-Apps, die auf dem iPad oder in der Mac-Spiegelung laufen, haben frei skalierbare Fenster. Das zugehörige Layout-Signal ist, dass die horizontale Size Class von compact auf regular kippt. Der alte Code if idiom == .phone produziert in solchen Fenstern das falsche Layout. Frag die Size Class.

Reichen Size Classes? Warum zusätzlich die Breite messen?

Sie reichen nicht, und die Klippe ist real. iPad-Vollbild und Split View halb sind beide (regular, regular), ihre Breiten unterscheiden sich jedoch um das Doppelte – in das eine passt eine Sidebar, in das andere nicht. Size Classes entscheiden Richtung (einspaltig oder geteilt), gemessene Breite entscheidet Grad (wie viele Spalten, wie groß). Beides ist ein Staffellauf, keine Wahl.

Wenn ich minimumSize deklariere, können Nutzer dann nicht kleiner ziehen?

minimumSize ist die Untergrenze, ab der dein Inhalt anfängt sich zu überdecken; Nutzer können nicht darüber hinaus ziehen. Das ist ein Überlappungsschutz, kein Feature-Gate gegen die Skalierung. Was du schuldest, ist Bedienbarkeit in jeder Größe von minimumSize bis maximumSize. Versagt eine Größe, ist die Anpassung unfertig – nicht einfach das Minimum erhöhen.

Was passiert, wenn ich UIRequiresFullScreen lösche?

Die App nimmt am Fenster-Skalieren teil, die seit iOS 26+ erwartete Vorgabe. Wer Legacy-Kompatibilität braucht, kann mit UIRequiresFullScreenIgnoredStartingWithVersion die Ignorier-Ab-Version angeben; Spiele geraten in diskretes Skalieren und wechseln nach jedem Ziehen in eine passende Bildschirmkonfiguration, was die Renderqualität eher wahrt.

Was muss eine SwiftUI-App wirklich tun?

Neu kompilieren, und die Skalierungsunterstützung ist da; keine neue API zu übernehmen. Prüfe stattdessen: Code, der auf UIScreen-Zeit-Annahmen baut; Größenurteile, die nur Size Classes nutzen ohne Messungs-Unterfütterung; Komponenten mit festem Frame, die in extremen Seitenverhältnissen reißen. Das Framework regelt das Makro. Die reißende Komponente ist meist die, die du selbst festgenagelt hast.

Quellen und Weiterlesen

Offizielle Quellen: WWDC25 Session 282 „Make your UIKit app more flexible", WWDC26 Session 278 „Modernize your UIKit app", die Abschnitte Layout und Designing for iPhone Duo der Human Interface Guidelines, die Dokumentation zu UISceneSizeRestrictions und UIWindowScene.Geometry sowie die Technotes TN3192: Migration von der verworfenen UIRequiresFullScreen-Kennung und TN3208: Anforderungen an den Launch Screen.

Weiterlesen auf dieser Site: Um zu sehen, wie derselbe Gedanke auf einem konkreten Gerät von Anfang bis Ende landet, lies Oberflächen für das iPhone Duo: vom Layout zum Code. Für die andere Seite – dass auch Daten mit dem Raum schrumen – sieh den Ratgeber zur persönlichen Basislinie. Weitere Fragen zu Produkt und Anpassung stehen in den häufigen Fragen.

Weiterlesen

Diese Ideen in Stress HRV ausprobieren

Im App Store laden

Diese Notizen teilen Produktgedanken für Wellness. Sie sind keine medizinische Beratung.