Определите фоновый статус с помощью SwiftUI

При использовании SwiftUI с iOS 13+, традиционные средства определения фонового состояния больше не работают. Например:

  • Методы AppDelegate applicationDidEnterBackground(_ application: UIApplication) и applicationDidBecomeActive(_ application: UIApplication) не вызываются.

  • Уведомления didEnterBackgroundNotification, willEnterForegroundNotification, didBecomeActiveNotification и willResignActiveNotification не отправляются.

В качестве альтернативы есть UIWindowSceneDelegate обратные вызовы: sceneDidBecomeActive(_ scene: UIScene), sceneWillResignActive(_ scene: UIScene), sceneWillEnterForeground(_ scene: UIScene), sceneDidEnterBackground(_ scene: UIScene)

Проблема с этими заменами заключается в том, что они относятся к одной из нескольких сцен, которые входят и выходят на передний план. Они не обеспечивают простой и понятный способ определить, находится ли все приложение на переднем плане или в фоновом режиме.

Определение статуса переднего и заднего плана приложения важно по причинам, не имеющим ничего общего с пользовательским интерфейсом. Некоторые функции iOS не работают без предупреждения, когда приложение не находится на переднем плане (два примера - сканирование по Bluetooth с подстановочными знаками и передача через iBeacon. .) Я часто разрабатываю фреймворки iOS, у которых вообще нет пользовательского интерфейса, поэтому мне нужен способ определения фона / состояния переднего плана приложения, который не зависит от вставки набора шаблонного кода в UIWindowSceneDelegate - он Для меня неразумно просить кого-нибудь, кто использует мою структуру, сделать это.

Есть ли какие-либо простые способы определить статус переднего плана / фона приложений в iOS 13 с помощью SwiftUI?


person davidgyoung    schedule 09.09.2020    source источник
comment
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { _ in у вас не работает?   -  person pawello2222    schedule 09.09.2020
comment
@ pawello222, я поправлюсь. Вопреки тому, что я сказал в своем вопросе, четыре уведомления, которые я говорю, не срабатывают, все равно срабатывают. Я был уверен, что в прошлый раз, когда я попробовал, этого не произошло, но, видимо, я ошибался. Если вы ответите на этот вопрос, я с радостью приму его.   -  person davidgyoung    schedule 10.09.2020
comment
в Введение в несколько Windows на iPad WWDC19 есть объяснение этого возможного несоответствие; примерно в 17:06 есть диаграмма, но весь доклад очень информативный   -  person lorem ipsum    schedule 19.02.2021


Ответы (2)


Вы также можете использовать UIApplication уведомления в SwiftUI:

  • didEnterBackgroundNotification
  • willEnterForegroundNotification
  • didBecomeActiveNotification
  • willResignActiveNotification

Вот пример:

NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: .main) { _ in
    // active
}

NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: .main) { _ in
    // inactive
}
person pawello2222    schedule 09.09.2020
comment
Это правильно. Мое заявление в моем вопросе о том, что они не работают, было ошибочным. - person davidgyoung; 10.09.2020

Я считаю, что правильным способом обработки событий в SwiftUI является использование onReceive.

Text("Hello, World!")
    .onReceive(NotificationCenter.default.publisher(for: UIApplication.didEnterBackgroundNotification)) { _ in
        // Action
    }
person Iaenhaall    schedule 18.02.2021
comment
Хотя приведенное выше может отлично работать для конкретной сцены, вопрос заключается в том, как определить состояние переднего плана / фона для всего приложения во многих сценах. - person davidgyoung; 18.02.2021