Что произойдет, если обновить массив, помеченный как @Published, из фонового потока?

«Что произойдет, если обновить массив, помеченный как @Published, из фонового потока?» — вопрос из категории Реактивное программирование, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Обновление свойства @Published из фонового потока приведет к нарушению требований потокобезопасности SwiftUI и вызовет предупреждение в runtime (Publishing changes from background threads is not allowed), а в худшем случае — к сбою интерфейса или крешу приложения.

Правильные подходы для обновления на главном потоке:

  1. Использование DispatchQueue.main.async:

    class ViewModel: ObservableObject {
        @Published var items: [String] = []
    
        func fetchData() {
            DispatchQueue.global().async {
                // Фоновая работа
                let newData = ["A", "B", "C"]
                DispatchQueue.main.async {
                    self.items = newData // Обновление на главном потоке
                }
            }
        }
    }
  2. Использование модификатора @MainActor:

    @MainActor
    class ViewModel: ObservableObject {
        @Published var items: [String] = []
    
        func updateItems() async {
            // Эта функция уже выполняется на MainActor
            items = await loadFromNetwork()
        }
    }

Ключевое правило: Все изменения, которые приводят к обновлению UI (через @Published, @State, @StateObject), должны выполняться на главном потоке (Main Actor).