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>
This commit is contained in:
co-authored by
Claude Opus 5
parent
e5e01838f7
commit
e7de8a9055
@@ -0,0 +1,68 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user