Skip to content
DeveloperMemos

How to Use onReceive Modifier in SwiftUI

SwiftUI, onReceive Modifier, Combine Framework2 min read

The onReceive modifier is used to specify a closure that should be called when a view's underlying data changes. This can be useful for updating the view's layout or triggering some other action when the data changes. The onReceive modifier is defined as follows:

1func onReceive<Publisher>(_: Publisher, perform: @escaping (Publisher.Output) -> Void) -> some View where Publisher : Combine.Publisher

The first argument to the onReceive modifier is a publisher that emits the data you want to observe. Publishers are a fundamental component of the Combine framework, which is used for reactive programming in SwiftUI. You can use any publisher that emits data of a type compatible with the closure you provide.

The second argument to the onReceive modifier is a closure that will be called whenever the publisher emits a new value. The closure takes a single argument of the same type as the publisher's output, and can perform any action you want in response to the data change.

Let's see an example of how to use the onReceive modifier. Suppose we have a view that displays a user's name, and we want to update the view whenever the user's name changes. We can use the onReceive modifier with a publisher that emits the user's name:

1struct UserView: View {
2 @ObservedObject var user: User
3
4 var body: some View {
5 Text("Hello, \(user.name)")
6 .onReceive(user.$name) { newName in
7 print("User name changed to \(newName)")
8 }
9 }
10}

In this example, we use the @ObservedObject property wrapper to declare a reference to a User object, which has a name property that we want to observe. We then define the view's body using a Text view that displays a greeting message with the user's name. Finally, we use the onReceive modifier to register a closure that will be called whenever the user's name changes. In this case, we simply print a message to the console to indicate that the name has changed.

It's worth noting that the onReceive modifier can be used with any publisher, not just @Published properties. You can create your own publishers or use any of the built-in publishers provided by the Combine framework. For example, you could use a Timer publisher to update the view periodically:

1struct CountdownView: View {
2 @State var timeRemaining = 60
3
4 var body: some View {
5 Text("\(timeRemaining) seconds remaining")
6 .onReceive(Timer.publish(every: 1, on: .main, in: .common).autoconnect()) { _ in
7 timeRemaining -= 1
8 }
9 }
10}

In this example, we use the @State property wrapper to declare a variable that holds the remaining time for a countdown. We then define the view's body using a Text view that displays the time remaining. Finally, we use the onReceive modifier with a Timer publisher that emits a new value every second, and subtract one from the time remaining each time the closure is called.

In summary, the onReceive modifier is a powerful tool for responding to changes in data in SwiftUI. By using the onReceive modifier with a publisher, you can register a closure that will be called whenever the data changes, allowing you to update the view's layout or trigger some other action in response. The onReceive modifier is particularly useful when you need to update the view's appearance or perform some other side effect when the data changes.