Local var inside GeometryReader/ViewBuilder

Original Post and title "View property depends on GeometryReader sizes"

So, I have a view that is a collection of randomly placed dots. Currently the computation of these dots is just random within the size that GeometryReader gives, but it become more complex later (it will need to be iterated over and referred to for adjustments and thus needs to be stored somewhere). For a given instance of Dots, after calculation they will remain constant (in usage, there may be multiple instances on screen, it may also be gestured off screen but then gestured back to, hence being stored).


The problem is I need the values from GeometryReader, but you can't declare variables in a ViewBuilder and self is immutable.

There's also the issue in using ForEach that CGSize doesn't conform to Hashable, but one problem at a time...


func randomOffset(maxWidth: CGFloat, maxHeight: CGFloat) -> CGSize {
    // ...
}

struct Dots: View {
    
    let quantity: Int
    let dot: some View = Circle()

    var offsets: [CGSize] = []
    
    init(_ quantity: Int) {
        self.quantity = quantity
    }
    
    mutating func genOffsets(maxWidth: CGFloat, maxHeight: CGFloat) {
        for _ in 0..            // will be more complex later...
            self.offsets.append(randomOffset(maxWidth: maxWidth, maxHeight: maxHeight))
        }
    }


 body: some View {
        GeometryReader { geom in
            genOffsets(maxWidth: geom.size.width, maxHeight: geom.size.height)
            ForEach(offsets, id: \.self) {offset in
                self.dot
                     .offset(offset))
            }
        }
    }
}


Edit: In terms of getting a variable inside of GeometryReader (or other ViewBuilders), it looks like the issue it to do with implicitly specifying return type https://forums.swift.org/t/local-vars-in-swiftui-builders/26672/7


Adding a return is still valid, but once the variable is there it errors saying the generic type Content can't be inferred, thus the de-generalising needs to be stated explicitly. For example, this works

GeometryReader<Text> { _ in
     let s = "hello"
     return Text(s)
}

thanks to the de-generlising GeometryReader's '<Content: View>' to '<Text>' and an explicit 'return' call.


But the view in my case is rather more complex than a simple 'Text' view and would be <VStack: <HStack: ...>> and so on. Is there something in between I can do?

Local var inside GeometryReader/ViewBuilder
 
 
Q