'Observe frame changes in SwiftUI

I have view that can be dragged and dropped on top of other views (lets say categories). To detect which category view I'm on top of, I store their frames in a frames array, which happens in onAppear of their invisible overlays. (This is based on Paul Hudsons implementation in this tutorial).

This works all nice and well, except when the position of those views change, e.g. in device orientation or windows resizing on iPad. This of course doesn't trigger onAppear, so the frames don't match anymore.

HStack() {
ForEach(categories) { category in
    ZStack {
        Circle()
        Rectangle()
            .foregroundColor(.clear)
            .overlay(
                GeometryReader { geo in
                    Color.clear
                        .onAppear {
                            categoryFrames[index(for: category)] = geo.frame(in: .global)
                        }
                }
            )
        }
    }
}

So any idea how to update the frames in those instances or how to differently observe them would be welcome.



Solution 1:[1]

I had a similar problem and this post inspired me in finding a solution. So maybe this will be useful to someone else. Just assign to the onChange modifier the same you did to onAppear and set it to fire when geo.size changes.

HStack() {
ForEach(categories) { category in
    ZStack {
        Circle()
        Rectangle()
            .foregroundColor(.clear)
            .overlay(
                GeometryReader { geo in
                    Color.clear
                        .onAppear {
                            categoryFrames[index(for: category)] = geo.frame(in: .global)
                        }
                        .onChange(of: geo.size) { _ in
                            categoryFrames[index(for: category)] = geo.frame(in: .global)
                        }
                }
            )
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 alex oliveira