SwiftUI с издателями NotificationCenter

Я хочу слушать уведомления, когда приложение переходит в фоновый режим и возвращается. Я пытаюсь использовать издателей NotificationCenter, и представление SwiftUI их слушает.
Я могу использовать несколько методов для этого, и я пытаюсь использовать два из них, но интересно то, что хотя все кажется законным, когда я помещаю подписчика в метод init(), он просто не работает.
Я попытался поместить его в ветку main, но безуспешно.
Кто-нибудь знает, почему?
Вот мой код:

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)
    }
}

Как ни странно, слушатель в модификаторе onReceive работает как шарм. В init() print("init") никогда не вызывается.


person hastoro11    schedule 01.01.2020    source источник


Ответы (2)


@State еще не готов в init, поэтому его нельзя использовать для таких целей. Подход может быть следующим:

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

в таком определенном cancellables вы можете хранить всех подписчиков, созданных в init, но вы не сможете использовать его позже в коде, но этот подход хорош для однажды определенных обработчиков уведомлений.

person Asperi    schedule 01.01.2020
comment
Спасибо, похоже, проблема. Мне все равно не нужна была оболочка @State, но в определенный момент Xcode начал жаловаться, что в структуре вы не можете изменять свойства. Но теперь он это принимает. - person hastoro11; 02.01.2020

Вы можете использовать onAppear?

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

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

См. onAppear:

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

Вроде замена на viewDidLoad

person Johnston    schedule 16.01.2020
comment
Я думаю, это больше похоже на viewDidAppear - person Piidro; 11.01.2021
comment
Будет ли это вызвано несколько раз? В таком случае действие также будет запускаться несколько раз. - person Rivera; 03.06.2021