Хотя мобильная разработка и не является основным профилем нашей компании, порой среди требований к корпоративному порталу оказывается его доступность с мобильных устройств. В связи с этим иногда приходится браться за нетипичные для нас задачи в виде разработки iOS и Android приложений. Однако оставим задачу систематического изложения основ мобильной разработки на другой раз. В этой заметке кратко зафиксируем, как наиболее просто решить проблему с красным значком с количеством уведомлений у иконки iOS-приложения, который не пропадает при переходе в программу. Речь идет о подобном красном кружке:
Зачастую происходит так, что при открытии приложения счетчик непрочитанных уведомлений не исчезает, а остается неизменным. Особенно часто такое возникает в случае, если переход происходит не по клику на уведомление в "Центре уведомлений", а непосредственно через экранное меню айфона.
Если мы хотим, чтобы все новые уведомления в приложении отмечались как прочитанные при переходе в приложение, то ответ кроется в модификации класса SceneDelegate. SceneDelegate - это класс в Swift, который отвечает за управление жизненным циклом конкретного экземпляра пользовательского интерфейса (сцены). Класс создает объект "контейнер" для элементов UIWindow, управляет состояниями приложения, размещением контента на странице, обработкой касаний разных элементов, переходами между фоновым и активным режимами.
Отличие SceneDelegate от AppDelegate в том, что последний предназначен для глобальной конфигурации всего приложения в целом. Там же происходит и регистрация Push-уведомлений, инициализация Firebase или иных уведомлений. Сейчас же нам нужен SceneDelegate, поскольку именно он обрабатывает событие открытия "сцены" приложения, при переходе в которую мы хотим обнулять счетчик уведомлений. Метод, который нам нужен для обработки события - sceneDidBecomeActive(_:). Он вызывается, когда сцена стала активной и готова к взаимодействию с пользователем.
Кусок кода на языке Swift, чтобы достичь поставленной задачи:
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let _ = (scene as? UIWindowScene) else {
return
}
}
func sceneDidBecomeActive(_ scene: UIScene) {
if #available(iOS 17.0, *) {
UNUserNotificationCenter.current().setBadgeCount(0) { error in
if let error = error { print("sceneDidBecomeActive ERROR: \(error)") }
}
} else {
UIApplication.shared.applicationIconBadgeNumber = 0
}
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
}
}
Для управления уведомлениями в iOS используется класс UNUserNotificationCenter. Во фрагменте кода выше мы используем его методы для сброса счетчика уведомлений на иконке приложения в ноль (метод setBadgeCount), а также для удаления уведомлений, пришедших от нашего приложения, в ленте "Центра уведомлений" (метод removeAllDeliveredNotifications). Метод удаления через UIApplication.shared.applicationIconBadgeNumber является устаревшим (для версий до iOS 17)