Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI with NotificationCenter publishers

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.

like image 922
hastoro11 Avatar asked Jan 01 '20 12:01

hastoro11


2 Answers

@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.

like image 198
Asperi Avatar answered Oct 23 '22 08:10

Asperi


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

like image 23
Johnston Avatar answered Oct 23 '22 09:10

Johnston