I am caught with a bizarre SwiftUI bug. I’ve a sheet that is presupposed to dimension itself based mostly on its content material (utilizing PreferenceKey + GeometryReader). Every little thing works positive till I attempt to change the consumer interface type utilizing overrideUserInterfaceStyle.
Once I change the theme like this, the sheet dimension immediately turns into 0 and onPreferenceChange is not even referred to as. This solely occurs on iOS 16.
You’ll be able to see the issue within the display screen recordings.
import SwiftUI
fileprivate struct IntrinsicContentSizePreferenceKey: PreferenceKey {
static let defaultValue: CGSize = .zero
static func scale back(worth: inout CGSize, nextValue: () -> CGSize) {
worth = nextValue()
}
}
fileprivate struct FittedPresentationDetentModifier: ViewModifier {
@State non-public var contentSize: CGSize = .zero
func physique(content material: Content material) -> some View {
content material
.overlay(
GeometryReader { proxy in
Shade.clear.choice(
key: IntrinsicContentSizePreferenceKey.self,
worth: proxy.dimension
)
}
)
.onPreferenceChange(IntrinsicContentSizePreferenceKey.self) { newSize in
print("→ present dimension: (contentSize)")
print("→ new dimension: (newSize)")
guard newSize != .zero else { return }
contentSize = newSize
}
.presentationDetents([.height(contentSize.height)])
.presentationCornerRadius(32.0)
}
}
fileprivate extension View {
func fittedPresentationDetent() -> some View {
modifier(FittedPresentationDetentModifier())
}
}
extension View {
func bottomSheet<Content material: View>(
isPresented: Binding<Bool>,
@ViewBuilder content material: @escaping () -> Content material
) -> some View {
self.sheet(isPresented: isPresented) {
content material()
.fittedPresentationDetent()
}
}
}
i created a pattern mission for testing.
import SwiftUI
struct ContentView: View {
@State non-public var showSheet = false
@Setting(.colorScheme) var colorScheme
var isDarkMode: Bool {
colorScheme == .darkish
}
var physique: some View {
NavigationView {
VStack(spacing: 20) {
Picture(systemName: isDarkMode ? "moon.fill" : "solar.max.fill")
.font(.system(dimension: 60))
.foregroundColor(isDarkMode ? .white : .yellow)
.padding()
Textual content("Present Theme: (isDarkMode ? "Darkish" : "Gentle")")
.font(.headline)
Button(motion: {
showSheet.toggle()
}) {
Textual content("Change Theme")
.font(.headline)
.padding()
.background(Shade.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.navigationTitle("Theme Switcher")
.bottomSheet(isPresented: $showSheet, content material: {
ThemeSettingsSheet(isDarkMode: isDarkMode)
})
}
}
}
struct ThemeSettingsSheet: View {
let isDarkMode: Bool
@Setting(.dismiss) var dismiss
var physique: some View {
Toggle(isOn: Binding(
get: { isDarkMode },
set: { newValue in
changeTheme(isDarkMode: newValue)
}
)) {
HStack {
Picture(systemName: isDarkMode ? "moon.fill" : "solar.max.fill")
.foregroundColor(isDarkMode ? .white : .yellow)
Textual content("Darkish Mode")
}
}
.padding()
}
non-public func changeTheme(isDarkMode: Bool) {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = windowScene.home windows.first else { return }
UIView.transition(with: window,
length: 0.3,
choices: .transitionCrossDissolve,
animations: {
window.overrideUserInterfaceStyle = isDarkMode ? .darkish : .gentle
}, completion: nil)
}
}
#Preview {
ContentView()
}
Anybody run into this? Any workarounds? Thanks!