Skip to content
DeveloperMemos

Avoiding State Changes in SwiftUI onAppear

SwiftUI, State Management, onAppear1 min read

One common issue that can arise when working with SwiftUI is a crash that occurs when you try to change an @State variable inside of the onAppear function. This can be a confusing problem, as it seems like it should be a straightforward operation.

The reason why this crash happens is because the onAppear function is called synchronously during the view's rendering process. If you try to change an @State variable within onAppear, it will trigger a re-render of the view. However, since the view is still in the process of rendering, this can lead to a recursive loop that crashes the app.

There are a couple of ways to solve this problem. The first is to call the service asynchronously. This will prevent the code from blocking the rendering process and allow the view to update correctly.

Here is an example of how to call a service asynchronously in onAppear:

1struct MyView: View {
2 @State private var data: String = ""
3
4 var body: some View {
5 Text(data)
6 .onAppear {
7 DispatchQueue.main.async {
8 // Call your service here
9 data = "Data from service"
10 }
11 }
12 }
13}

Another way to solve this problem is to dispatch the change to the @State variable to the next runloop execution. This will break the cycle and allow the view to update correctly.

Here is an example of how to dispatch the change to the next runloop execution:

1struct MyView: View {
2 @State private var data: String = ""
3
4 var body: some View {
5 Text(data)
6 .onAppear {
7 DispatchQueue.main.async {
8 // Call your service here
9 self.objectWillChange.send()
10 data = "Data from service"
11 }
12 }
13 }
14}

By following either of these solutions, you can avoid the crash that occurs when changing an @State variable inside of the onAppear function! Happy coding.