Files
Flaro/Flixy/Views/Navigation/SidebarOverlap.swift
T
ScarriffleandClaude Opus 5 e7de8a9055 Bilder ohne Warten — und der Beweis, dass der Mac die Leiste selbst zeichnet
Der Schriftzug hing weiter nicht an der Animation, und der Zwischenspeicher war
nicht schuld: er lag im Actor, und ein `await` kostet immer mindestens einen
Durchlauf. Das neue Bild erschien deshalb im ersten Bild ohne Schriftzug und im
zweiten mit — er sprang also getrennt herein, obwohl er längst da war.

Der Speicher liegt jetzt außerhalb des Actors und lässt sich beim Zeichnen
lesen. Das gilt für alle Bilder: auch eine zurückscrollende Kachel blitzt nicht
mehr kurz grau auf.

Zur Seitenleiste auf dem Mac, gemessen statt vermutet: `automatic` löst sich
laut Apples eigener Beschreibung auf iOS zu `overlap` auf (die Leiste schwebt
über dem Inhalt) und auf macOS zu `tile` (sie schiebt ihn zur Seite und klebt
am Fensterrand). Der Griff dorthin sitzt richtig — derselbe Weg hat die Leiste
auf Kommando ganz ausgeblendet —, aber `overlap` wird auf dem Mac
stillschweigend verworfen. Die Bitte bleibt trotzdem stehen; sie kostet nichts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 17:40:46 +02:00

69 lines
2.9 KiB
Swift

#if os(iOS)
import SwiftUI
import UIKit
/// Bittet die Seitenleiste, den Inhalt zu **überlagern** statt ihn zu verdrängen.
///
/// `UITabBarControllerSidebar.preferredLayout` steht ab Werk auf `automatic`,
/// und das löst sich laut Apples eigener Beschreibung je nach Gerät anders auf:
/// auf iOS zu `overlap` — die Leiste schwebt als eigene Fläche über dem Inhalt —
/// und auf macOS zu `tile`, wo sie den Inhalt zur Seite schiebt und selbst am
/// Fensterrand klebt. Das ist der Unterschied, den man zwischen iPad und Mac
/// sieht, und er kommt nicht aus dieser App.
///
/// **Unter Mac Catalyst gemessen: es hilft dort nicht.** Der Griff sitzt
/// richtig — zum Beweis hat derselbe Weg die Leiste auf Kommando ganz
/// ausgeblendet —, aber `overlap` wird auf dem Mac stillschweigend verworfen
/// und es bleibt bei `tile`. Der Aufruf bleibt trotzdem stehen: er ist die
/// richtige Bitte, er kostet nichts, und sollte „Designed for iPad" sich näher
/// am iPhone-Bau verhalten als Catalyst, greift er dort.
///
/// SwiftUI reicht die Eigenschaft nicht durch, also wird der zuständige
/// `UITabBarController` gesucht. Gesucht wird vom eigenen Platz aus nach oben
/// bis zur Wurzel und von dort nach unten — die Leiste liegt in der
/// SwiftUI-Sicht *über* uns, nicht unter uns, und die reine Elternkette führt
/// deshalb an ihr vorbei.
struct SidebarOverlapRequest: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
Probe()
}
func updateUIViewController(_ controller: UIViewController, context: Context) {}
/// Ein Controller, der nichts zeigt und nur da ist, um im Baum zu stehen.
private final class Probe: UIViewController {
override func didMove(toParent parent: UIViewController?) {
super.didMove(toParent: parent)
apply()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// Ein zweites Mal: beim ersten Anhängen steht der
// Tab-Controller noch nicht zwingend im Baum.
apply()
}
private func apply() {
guard let controller = Self.tabBarController(from: self) else { return }
guard controller.sidebar.preferredLayout != .overlap else { return }
controller.sidebar.preferredLayout = .overlap
}
private static func tabBarController(from start: UIViewController) -> UITabBarController? {
var root = start
while let parent = root.parent { root = parent }
return search(root)
}
private static func search(_ controller: UIViewController) -> UITabBarController? {
if let found = controller as? UITabBarController { return found }
for child in controller.children {
if let found = search(child) { return found }
}
return nil
}
}
}
#endif