September 27, 2024
86. Пример работы с NotificationCenter в SwiftUI
NotificationCenter — позволяет отправлять события и подписываться на них в нужных местах приложения, чтобы выполнять какие-то действия. Покажу как это работает в SwiftUI.
Алгоритм действий
- Сверстаем переиспользуемую вьюху для двух примеров работы с
NotificationCenter - Нужно подписаться на событие
NotificationCenter. В нашем примере сделаем 2 варианта реализации: с использованиемonReceiveпрямо во вьюхе и с использованиемCombineво вьюмодели - Нужно отправить уведомление через
NotificationCenter. В моих примерах будем отправлять текст в полеobject.
Подготовка
Чтобы не писать каждый раз название уведомления, сделаем для него константу:
enum NotificationCenterExample {
static let notificationName = Notification.Name("демо.уведомление")
}
Верстаем вьюху для примеров
struct DemoView: View {
let text: String
let clearAction: () -> Void
let sendAction: () -> Void
var body: some View {
ZStack {
if text.isEmpty {
Button("Отправить уведомление", action: sendAction)
.transition(.move(edge: .bottom).combined(with: .opacity))
} else {
VStack(spacing: 20) {
Text(text).font(.title)
Button("Очистить", action: clearAction)
}
.transition(.slide.combined(with: .opacity).combined(with: .scale))
}
}
.animation(.default, value: text.isEmpty)
}
}
Пример № 1
Подписываемся на уведомление во вьюхе:
extension NotificationCenterExample {
struct OnReceiveExample: View {
@State private var notificationText = ""
var body: some View {
DemoView(
text: notificationText,
clearAction: { notificationText = "" },
sendAction: {
NotificationCenter.default.post(
name: notificationName,
object: "Привет от NotificationCenter!"
)
}
)
.onReceive(NotificationCenter.default.publisher(for: notificationName)) { notification in
if let text = notification.object as? String {
notificationText = text
}
}
}
}
}
Пример №2
Делаем вьюмодель
final class ViewModel: ObservableObject {
@Published private(set) var text = ""
private var cancellable: AnyCancellable?
init() {
cancellable = NotificationCenter.default
.publisher(for: notificationName)
.sink { notification in
if let text = notification.object as? String {
self.text = text
}
}
}
deinit { cancellable?.cancel() }
func sendAction() {
NotificationCenter.default.post(
name: notificationName,
object: "Привет от NotificationCenter!"
)
}
func clearAction() { text = "" }
}
Делаем экран
extension NotificationCenterExample {
struct ViewModelExample: View {
@StateObject private var viewModel = ViewModel()
var body: some View {
DemoView(
text: viewModel.text,
clearAction: viewModel.clearAction,
sendAction: viewModel.sendAction
)
}
}
}
Заключение
NotificationCenter может пригодиться в разных ситуациях, в том числе когда нужно быстро реализовать какую-то связку действий для MVP фичи, например.
Также можно подписываться на системные события вроде появления/скрытия клавиатуры, сворачивания/разворачивания приложения.
Код для этой статьи можно посмотреть тут, другие статьи по разработке - тут, а про инвестиции - тут.