So I've seen some approach to read the CGRect of a swiftui view using a technique where you setup a background containing a GeometryReader that is used to read the size of the view the background is set up. My issue is that this doesn't work if the view you're setting the background to has some ifs in it for example. See the code below for reference:
import SwiftUI
struct RectPreferenceKey: PreferenceKey {
static var defaultValue = CGRect.zero
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
value = nextValue()
}
}
struct ChildRectReaderModifier: ViewModifier {
@Binding var rect: CGRect
func body(content: Content) -> some View {
content
.background(
GeometryReader { proxy in
Color.clear.preference(
key: RectPreferenceKey.self,
value: proxy.frame(in: .global)
)
}
)
.onPreferenceChange(RectPreferenceKey.self) { preferences in
if preferences != .zero && self.rect != preferences {
self.rect = preferences
}
}
}
}
extension View {
func childRectReader(_ rect: Binding<CGRect>) -> some View {
modifier(ChildRectReaderModifier(rect: rect))
}
}
struct ContentView: View {
@State var showOptionalText = false
@State var rect = CGRect.zero
var body: some View {
VStack {
Text("\(rect.width)")
Button {
showOptionalText.toggle()
} label: {
Text("Toggle")
}
VStack {
Text("Hello, world!")
Text("Hello, world!")
if showOptionalText {
Text("Hello, world!")
}
Text("Hello, world!")
}
.childRectReader($rect)
}
}
}
In the example above, the printed width is saying 0 unless I remove the if inside the inner VStack
Any idea why this happens? or any potential fixes?