Search code examples
swiftuiios17

Method equivalent `onReceive` in iOS 17 with Observable


With iOS Version 16 and older.
In some cases, we can use Combine and listener object change in ObservableObject or StateObject by onReceive. Example: Listener on Root View, In-app inactive ... etc. (In some case onChange could be not working)

So when migrating the project to iOS 17+, what method is equivalent onReceive in iOS 17 with Observable?

@Bindable in this case could be not the same.

struct ContentView: View {
    @State private var vm = ContentViewModel()
    
    var body: some View {
        VStack {
            Button(action: {
                vm.number += 1
            }, label: {
                Text("\(vm.number)")
            })
        }
        /// What method equivalent `onReceive` in this case
        .onReceive(vm.$number) { _ in
            print("onReceive: \(vm.number)")
        }
    }
}

@Observable
final class ContentViewModel {
    var number = 0
}

Solution

  • you could try this approach:

    import SwiftUI
    import Observation
    import Combine
    
    @Observable class ContentViewModel {
        var number = 0
    }
    
    struct ContentView: View {
        @State private var vm = ContentViewModel()
        
        var body: some View {
            VStack {
                Button("\(vm.number)") {
                    vm.number += 1
                }.buttonStyle(.bordered)
            }
            .onReceive(vm.number.words.publisher) { _ in
                print("---> words onReceive: \(vm.number)")
            }
            // or
            .onReceive(Just(vm.number)) { _ in
                print("---> Just onReceive: \(vm.number)")
            }
        }
    }