ios – My Customized Display Dimensions Do Not Match UIScreen.major.bounds in SwiftUI

ios – My Customized Display Dimensions Do Not Match UIScreen.major.bounds in SwiftUI


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”?

Leave a Reply

Your email address will not be published. Required fields are marked *