My App keeps on crashing when I change the device orientation if I did set a scrollPosition
before.
My ContentView()
looks smth like this - where I'm reading out the display-size.
GeometryReader { display in
VStack {
HeaderView()
MainScrollView(display: display)
FooterView()
}
}
Passing display
on to the MainScrollView()
, where - inside a ScrollViewReader
an if-else
-statement checks if it should load the PortraitMainView()
or the `LandscapeMainView()
struct MainScrollView: View {
var display: GeometryProxy
var body: some View {
ScrollViewReader { scrollPosition in
ZStack {
ScrollView {
if display.size.width > display.size.height {
LandscapeMainView()
} else {
PortraitMainView()
}
}
Button(action: {
withAnimation {
scrollPosition.scrollTo("C", anchor: .top)
}
}, label: {
Text("Scroll to Position C")
} )
}
}
}
}
LandscapeMainView() and PortaitMainView() look like this:
LandscapeMainView: View {
var body: some View {
VStack {
Text("Item A")
.id("A")
Text("Item B")
.id("B")
Text("Item C")
.id("C")
Text("Item D")
.id("D")
Text("Item E")
.id("E")
}
}
}
It all works fine, I can flip the orientation and it changes from LandscapeMainView()
to PortraitMainView()
and vice versa.
Also, setting a scrollPosition
works like a charm in Landscape and Portrait Mode.
Only after I set a scrollPosition
and then change the orientation my device freezes, giving me an Thread 1: EXC_BAD_ACCESS (code=1, address=0x30)
as output. The Screen still shows the Portrait mode, tilted on the Landscape, leaving half of the screen blank.
Is there a better way to handle screen orientation and scrollviews in SwiftUI?
GeometryProxy
causes issues when you try to pass it anywhere (for me as well).
SwiftUI is closed source, so I can't explain what magical pointers issue is happening here. But this code is confirmed to be working as per comments.
GeometryReader { display in
VStack {
HeaderView()
MainScrollView(display: display.size.width > display.size.height)
FooterView()
}
}
struct MainScrollView: View {
var display: Boolean
var body: some View {
ScrollViewReader { scrollPosition in
ZStack {
ScrollView {
if display {
LandscapeMainView()
} else {
PortraitMainView()
}
}
Button(action: {
withAnimation {
scrollPosition.scrollTo("C", anchor: .top)
}
}, label: {
Text("Scroll to Position C")
} )
}
}
}
}
Bonus: same crashes happen with ScrollViewProxy
, be careful with those.
My uneducated guess, why this happening: GeometryProxy
is holding reference to parent widget, which is deallocated while being rebuilt, but child widget isn't rebuilt because argument didn't changed so it hits deallocated pointer.