I’m making an attempt to calculate the display dimension and content material dimension of a view in my SwiftUI app. Nonetheless, I’ve encountered the next points:
1. Mismatch Between geometry.dimension and UIScreen.major.bounds:
-
When utilizing geometry.dimension in a GeometryReader, the scale don’t
match UIScreen.major.bounds as a result of the previous excludes protected space
insets, whereas the latter contains them. -
To resolve this, I added the protected space insets to geometry.dimension utilizing
the getTotalSize perform in my code.
2. Points in iOS 16.4 Simulator When Orientation Adjustments:
-
My code works positive in iOS 15, iOS 17, and iOS 16 units, however not in
the iOS 16.4 simulator. -
To handle this, I attempted updating the scale utilizing .onChange(of:
geometry.safeAreaInsets) as an alternative of .onChange(of: geometry.dimension).
This workaround appears to resolve the difficulty for all situations.
3. onGeometryChange modifier Not Discovered:
- I tried to make use of onGeometryChange, which is meant to deal with
geometry adjustments extra elegantly. Nonetheless, I get the next error:
Worth of kind ‘ContentSizeViewModifier.Content material’ (aka ‘_ViewModifier_Content’) has no member
‘onGeometryChange’.
My Code
import SwiftUI
struct ContentView: View {
@State personal var contentSize: CGSize = .zero
@State personal var screenSize: CGSize = .zero
var physique: some View {
HStack {
VStack(spacing: 10) {
Textual content("Display width: (screenSize.width) (UIScreen.major.bounds.width)")
Textual content("Display peak: (screenSize.peak) (UIScreen.major.bounds.peak)")
HStack {
Spacer()
VStack {
Textual content("Hiya World")
.font(.largeTitle)
Textual content("Welcome to World")
.font(.title)
}
Spacer()
}
.background(Coloration.yellow)
.contentSize(dimension: $contentSize)
Textual content("Content material width: (contentSize.width)")
Textual content("Content material peak: (contentSize.peak)")
}
}
.screenSize(dimension: $screenSize)
}
}
struct ScreenSizeViewModifier: ViewModifier {
@Binding var dimension: CGSize
func physique(content material: Content material) -> some View {
ZStack {
Coloration.clear
content material
}
.ignoresSafeArea()
.contentSize(dimension: $dimension)
}
}
struct ContentSizeViewModifier: ViewModifier {
@Binding var dimension: CGSize
func getTotalSize(geometry: GeometryProxy) -> CGSize {
let (dimension, safeAreaInsets) = (geometry.dimension, geometry.safeAreaInsets)
var width: CGFloat = dimension.width
var peak: CGFloat = dimension.peak
width += safeAreaInsets.main + safeAreaInsets.trailing
peak += safeAreaInsets.prime + safeAreaInsets.backside
return CGSize(width: width, peak: peak)
}
func physique(content material: Content material) -> some View {
// if #out there(iOS 16, *) {
// content material
// .onGeometryChange(for: CGSize.self) { proxy in
// proxy.dimension
// } motion: { newVal in
// dimension = newVal
// }
// } else {
content material
.background(
GeometryReader { geometry in
Coloration.clear
.onAppear {
dimension = getTotalSize(geometry: geometry)
print("onAppear Dimension: (dimension)")
}
.onChange(of: geometry.dimension) { _ in
dimension = getTotalSize(geometry: geometry)
print("onChange Dimension: (dimension)")
}
}
)
// }
}
}
extension View {
func contentSize(dimension: Binding) -> some View {
return modifier(ContentSizeViewModifier(dimension: dimension))
}
func screenSize(dimension: Binding) -> some View {
return modifier(ScreenSizeViewModifier(dimension: dimension))
}
}
#Preview {
ContentView()
}
Can anybody please strive clarify each situation root trigger and resolution for it?
Is there a greater or extra dependable strategy to calculate the view dimension with out manually including safeAreaInsets to geometry.dimension?
Moderator, please don’t deal with this query as associated to all points; it pertains to a single query solely”?