Ответ
UIStackView, как и любой другой компонент UIKit, не является потокобезопасным. Все манипуляции с его свойствами и иерархией вложенных представлений (addArrangedSubview, removeArrangedSubview, изменение axis, spacing и т.д.) должны выполняться строго на главной потоке (Main Thread).
Причина: UIKit внутренне использует небезопасные для многопоточности структуры данных. Параллельные изменения из нескольких потоков приводят к неопределенному поведению и крашам.
Правильный подход: Все обновления UI должны быть обернуты в вызов DispatchQueue.main.
// Фоновый поток (например, после сетевого запроса)
DispatchQueue.global(qos: .background).async {
let newView = UIView()
// ... настройка newView
// НЕПРАВИЛЬНО - вызовет краш или неопределенное поведение
// self.stackView.addArrangedSubview(newView)
// ПРАВИЛЬНО - переход на главный поток
DispatchQueue.main.async {
self.stackView.addArrangedSubview(newView)
// Любые другие обновления UIStackView
}
}
Как проверить поток? Используйте Thread.isMainThread для отладки.
if Thread.isMainThread {
stackView.isHidden = true
} else {
DispatchQueue.main.async { [weak self] in
self?.stackView.isHidden = true
}
}
Исключение: Чтение некоторых свойств UI (например, frame, bounds) из фонового потока может быть безопасным, но это поведение не гарантировано документацией. Рекомендуется всегда выполнять любые взаимодействия с UIKit на главном потоке.