SwiftUI with NotificationCenter publishers
Asked Answered
K

2

17

I want to listen to notifications when the app goes to the background and comes back. I'm trying to use the NotificationCenter publishers and have the SwiftUI view listen to them.
I can use a few methods to do it and I'm trying to use two of them but the interesting thing is, that although all seem legit when I put the subscriber in the init() method, it just does not work.
I tried to put it on the main thread but still no success.
Does anyone have any idea why?
Here's my code:

struct ContentView: View {
    @State var isActive = true
    @State var cancellables = Set<AnyCancellable>()
    var body: some View {
        ZStack {
            Image("background")
                .resizable()
                .scaledToFill()
                .edgesIgnoringSafeArea(.all)                        
        }
        .onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in
            self.isActive = false
        }
        .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification), perform: {_ in
            self.isActive = true
        })
    }

    init() {
        NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)
         //   .receive(on: RunLoop.main)
            .sink(receiveValue: { _ in
                print("init")
            }
            .store(in: &cancellables)
    }
}

Strangely the listener in the onReceive modifier works like a charm. In the init() the print("init") never gets called.

Kunming answered 1/1, 2020 at 12:26 Comment(0)
C
18

@State is not ready yet in init, so it cannot be used for such purposes. The approach can be as follows:

var cancellables = Set<AnyCancellable>()
init() {
    NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)
        .sink(receiveValue: { _ in
            print(">> in init")
        })
        .store(in: &cancellables)
}

in such defined cancellables you can store all subscribers created in init, but you will not be able to use it later in code, but this approach is good for once defined notification handlers.

Cule answered 1/1, 2020 at 13:11 Comment(1)
Thanks, that seems to be the problem. I did not want the @State wrapper anyway but at a certain point Xcode started complaining that in a struct you can't modify the properties. But now it accepts it.Kunming
K
0

Can you use onAppear?

...
...
  var body: some View {
  ... your body code
  }.onAppear(perform: loadNotification)

  private func loadNotification() {
     NotificationCenter.default.publisher(
     ....
  }

See onAppear:

https://developer.apple.com/documentation/swiftui/view/3278614-onappear

It seems to be the replacement for viewDidLoad

Kruger answered 16/1, 2020 at 13:16 Comment(2)
I think it is more like the viewDidAppearMurphy
Will this be called multiple times? If so the action will also be triggered multiple timesSwordcraft

© 2022 - 2024 — McMap. All rights reserved.