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

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


I’m making an attempt to calculate the display screen 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.principal.bounds:

  • When utilizing geometry.dimension in a GeometryReader, the scale don’t
    match UIScreen.principal.bounds as a result of the previous excludes secure space
    insets, whereas the latter contains them.

  • To resolve this, I added the secure space insets to geometry.dimension utilizing
    the getTotalSize operate in my code.

2. Points in iOS 16.4 Simulator When Orientation Adjustments:

  • My code works high-quality in iOS 15, iOS 17, and iOS 16 gadgets, however not in
    the iOS 16.4 simulator.

  • To deal with this, I attempted updating the dimensions utilizing .onChange(of:
    geometry.safeAreaInsets) as an alternative of .onChange(of: geometry.dimension).
    This workaround appears to resolve the difficulty for all eventualities.

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 sort ‘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.principal.bounds.width)")
                Textual content("Display top: (screenSize.top) (UIScreen.principal.bounds.top)")
              
                HStack {
                    Spacer()
                    VStack {
                        Textual content("Howdy World")
                            .font(.largeTitle)
                        
                        Textual content("Welcome to World")
                            .font(.title)
                    }
                    Spacer()
                }
                .background(Shade.yellow)
                .contentSize(dimension: $contentSize)
                
                Textual content("Content material width: (contentSize.width)")
                Textual content("Content material top: (contentSize.top)")
            }
        }
        .screenSize(dimension: $screenSize)
    }
}

struct ScreenSizeViewModifier: ViewModifier {
    @Binding var dimension: CGSize
    func physique(content material: Content material) -> some View {
        ZStack {
            Shade.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 top: CGFloat = dimension.top
        width += safeAreaInsets.main + safeAreaInsets.trailing
        top += safeAreaInsets.high + safeAreaInsets.backside
        return CGSize(width: width, top: top)
    }
    
    func physique(content material: Content material) -> some View {
//        if #obtainable(iOS 16, *) {
//            content material
//                .onGeometryChange(for: CGSize.self) { proxy in
//                       proxy.dimension
//                } motion: { newVal in
//                    dimension = newVal
//                }
//        } else {
        content material
            .background(
                GeometryReader { geometry in
                    Shade.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<CGSize>) -> some View {
        return modifier(ContentSizeViewModifier(dimension: dimension))
    }
    
    func screenSize(dimension: Binding<CGSize>) -> some View {
        return modifier(ScreenSizeViewModifier(dimension: dimension))
    }
}


#Preview {
    ContentView()
}


Can anybody please attempt clarify every concern root trigger and resolution for it?

Is there a greater or extra dependable option 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”?

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 
rooshohttps://www.roosho.com
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog. 

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here


Latest Articles

author avatar
roosho Senior Engineer (Technical Services)
I am Rakib Raihan RooSho, Jack of all IT Trades. You got it right. Good for nothing. I try a lot of things and fail more than that. That's how I learn. Whenever I succeed, I note that in my cookbook. Eventually, that became my blog.