Перейти к основному содержимому
Версия: 5.9.0

Делегат SDK (ChatCenterUISDKDelegate)

ChatCenterUISDKDelegate — протокол для получения событий от SDK. Все методы имеют дефолтные реализации (пустые; didOpen возвращает false), поэтому реализуйте только те, которые нужны.

Потокобезопасность

В текущей версии SDK все методы делегата фактически вызываются на главном потоке, но это не зафиксировано контрактом — протокол не помечен @MainActor. Для надёжности оборачивайте UI-обновления в DispatchQueue.main.async:

func chatCenterUI(chatCenter: ChatCenterUISDK, didChangeUnreadMessages count: Int) {
DispatchQueue.main.async {
self.updateBadge(count: count)
}
}

Подключение делегата

Назначьте делегат после инициализации SDK:

chatCenterSDK.delegate = self

Объявите соответствие протоколу в нужном классе:

extension MyViewController: @preconcurrency ChatCenterUISDKDelegate {
// реализуйте нужные методы
}

Атрибут @preconcurrency нужен только при сборке со строгим concurrency-чекером (SWIFT_STRICT_CONCURRENCY=complete или Swift 6). Без него — можно опустить.


Методы делегата

didChangeUnreadMessages

func chatCenterUI(chatCenter: ChatCenterUISDK, didChangeUnreadMessages count: Int)

Вызывается при изменении количества непрочитанных сообщений.

Когда вызывается:

  • При изменении счётчика непрочитанных — после того как загружена история чата (SDK подгружает историю автоматически после authorize(user:), открывать экран чата для этого не требуется).
  • Периодически по REST-запросу getUnreadMessagesCount, если задан ChatConfig.unreadMessageCountDelay > 0. SDK делает следующий запрос спустя unreadMessageCountDelay секунд после завершения предыдущего — фактический интервал может быть больше указанного значения на время выполнения запроса.
  • Однократно со значением 0 при авторизации нового пользователя (другой identifier или токен). Повторная авторизация того же пользователя с тем же токеном не триггерит этот вызов.

После deauthorizeUser делегат перестаёт получать обновления счётчика до следующей авторизации.

Параметры:

  • count: Количество непрочитанных сообщений. 0 означает отсутствие непрочитанных.
Обновление бейджа, когда чат закрыт

Пока экран чата не открыт, делегат не получает мгновенных обновлений на каждое входящее сообщение — счётчик доставляется по REST-полингу с интервалом unreadMessageCountDelay секунд. Если unreadMessageCountDelay не задан или равен 0, полинг не выполняется, и делегат не будет вызываться до следующего открытия чата.

Для обновления бейджа при возврате приложения в foreground или при получении пуша дополнительно вызывайте getUnreadMessagesCount(completion:) из ChatCenterUISDK — completion приходит на main thread:

// AppDelegate / SceneDelegate
func applicationWillEnterForeground(_ application: UIApplication) {
guard let sdk = chatCenterSDK else { return }
do {
try sdk.getUnreadMessagesCount { [weak self] result in
if case let .success(count) = result {
self?.updateChatBadge(count)
}
}
} catch {
// Пользователь ещё не авторизован — обновим счётчик после authorize.
}
}

Пример — обновление бейджа на кнопке чата:

func chatCenterUI(chatCenter: ChatCenterUISDK, didChangeUnreadMessages count: Int) {
DispatchQueue.main.async {
self.chatButton.badge = count > 0 ? "\(count)" : nil
}
}

didReceiveNetwork

func chatCenterUI(chatCenter: ChatCenterUISDK, didReceiveNetwork error: Error)

Вызывается при ошибке REST-запроса или загрузки файла.

Только REST, не WebSocket

В текущей версии метод сообщает только об ошибках REST-слоя (включая upload файлов). Разрывы и ошибки WebSocket-соединения через этот callback не приходят — для отслеживания статуса real-time канала используйте отдельные индикаторы (например, состояние при send(message:), который бросает ChatCenterUISendMessageError.webSocketNotActive).

Пример:

func chatCenterUI(chatCenter: ChatCenterUISDK, didReceiveNetwork error: Error) {
Analytics.log("chat_network_error", parameters: ["error": error.localizedDescription])
}

didOpen url

func chatCenterUI(chatCenter: ChatCenterUISDK, didOpen url: URL) -> Bool

Вызывается перед открытием URL из сообщения чата (ссылки в тексте).

Возвращаемое значение:

  • true — ссылка обработана вашим приложением, SDK ничего не делает
  • false — SDK пытается открыть URL через UIApplication.shared.open(_:), но только если UIApplication.shared.canOpenURL(url) вернул true. Иначе ссылка молча игнорируется.
Поведение по умолчанию

Если метод не реализован, SDK действует как при возврате false — пытается открыть ссылку через UIApplication.shared.open(_:) с проверкой canOpenURL.

LSApplicationQueriesSchemes

canOpenURL возвращает false для любой схемы, не указанной в LSApplicationQueriesSchemes в Info.plist вашего приложения. Если в чате встречаются ссылки tel:, mailto:, кастомные deeplink-схемы или сторонние приложения, добавьте их явно:

<key>LSApplicationQueriesSchemes</key>
<array>
<string>tel</string>
<string>mailto</string>
<string>myapp</string>
</array>

Иначе пользователь нажмёт на ссылку и не увидит никакой реакции, а SDK не выдаст ошибку.

Пример — перехват deeplink, внешние ссылки через SFSafariViewController:

import SafariServices

func chatCenterUI(chatCenter: ChatCenterUISDK, didOpen url: URL) -> Bool {
// Обработать внутренний deeplink приложения
if url.scheme == "myapp" {
DeepLinkRouter.handle(url)
return true
}
// Внешние ссылки открыть через Safari в приложении
let safariVC = SFSafariViewController(url: url)
present(safariVC, animated: true)
return true
}
Возврат значения синхронный

didOpen возвращает Bool синхронно: решение «обрабатываю сам» (true) или «пусть SDK сам откроет» (false) SDK получает немедленно. Асинхронные проверки URL внутри метода невозможны — если решение зависит от сетевого запроса, верните false (с учётом ограничений canOpenURL выше) и обрабатывайте URL отдельно.


didLog

func chatCenterUI(chatCenter: ChatCenterUISDK, didLog event: String)

Вызывается при каждом событии логирования SDK. Используется для передачи логов SDK в собственную систему — Firebase Crashlytics, Sentry, OSLog.

Зависимость от logLevel

Метод подчиняется ChatLoggerConfig.logLevel — события передаются делегату только если их уровень входит в настроенный logLevel. При значении по умолчанию .off делегат не получит ни одного события. Для приёма всех логов в делегат используйте ChatLoggerConfig(logLevel: .all). Дополнительная фильтрация в обработчике делегата остаётся на стороне вашего кода.

Пример:

func chatCenterUI(chatCenter: ChatCenterUISDK, didLog event: String) {
os_log("%{public}@", log: .default, type: .debug, event)
}

Сводная таблица методов

МетодКогда вызываетсяВозвращает
didChangeUnreadMessagesПри изменении счётчика непрочитанных (после загрузки истории) и по REST-полингу с задержкой ChatConfig.unreadMessageCountDelay, если он задан
didReceiveNetworkПри ошибке REST-запроса или загрузки файла (WebSocket-ошибки не приходят)
didOpen urlПеред открытием URL из сообщения чатаBool (обработана?)
didLogПри событии логирования SDK, уровень которого попадает в ChatLoggerConfig.logLevel

Связанные разделы