Post

Replies

Boosts

Views

Activity

ScrollViewProxy scrollTo in onAppear may cause state changes to be lost
Scrolling to a SwiftUI view with the onAppear method can cause state changes of published values from an ObservableObject to be lost and a view to be displayed in an incorrect state. Here is a demo showing the problem: struct ContentView: View { @StateObject private var viewModel = ContentViewModel() @Namespace private var state2ID var body: some View { ScrollViewReader { scrollProxy in ScrollView(.vertical) { VStack(spacing: 15) { if viewModel.state2 { VStack { Text("State2 is set") } .id(state2ID) .onAppear { print("scrolling") withAnimation { scrollProxy.scrollTo(state2ID) } } } VStack(spacing: 0) { Text("State1: \(viewModel.state1)") Text("State1 changes from 'false -> true -> false' when the button is pressed.") .font(.footnote) } Button("Toggle States") { viewModel.toggleStates() } .buttonStyle(.bordered) Color.teal .frame(height: 900) } .padding() } } } } @MainActor final class ContentViewModel: ObservableObject { @Published private(set) var state1 = false @Published private(set) var state2 = false private var stateToggle = false func toggleStates() { Task { @MainActor in state1 = true defer { // This change never becomes visible in the view! // state1 will be improperly shown as 'true' when this method returns while it actually is 'false'. print("Resetting state1") state1 = false } stateToggle.toggle() if stateToggle { withAnimation { state2 = true } } else { state2 = false } } } } After pressing the button, “State1: true” is displayed in the view, which no longer corresponds to the actual value of the view model property, which is false. Effectively, the change in the defer call of the toggleStates method is lost and the view is no longer in sync with the actual state values of the view model. Tested with iOS 17.5 and 18.0 (devices + simulators)
1
0
331
Sep ’24
Xcode 16 no longer sets ENABLE_PREVIEWS=YES for preview builds
Up until now, it was possible to check in build scripts via the ENABLE_PREVIEWS environment variable whether a build for a SwiftUI preview is being executed. In addition, it was also possible to conditionally compile code for SwiftUI or exclude it from compilation using this variable. This no longer works with Xcode 16 and the new SwiftUI Preview compilation! There is still the option to switch to the old system with the "Use Legacy Previews Execution" setting, but as stated in the release notes, this option will be removed at some point. Which brings us back to the old problem of not being able to exclude build scripts from preview builds and not being able to prevent certain code from being compiled / add special code for SwiftUI previews. This is a terrible situation, especially for more complex projects in which precisely the points mentioned are important for the build process. I seriously hope Apple provides us with another environment variable for SwiftUI preview builds that we can use.
7
9
1.8k
Aug ’24