SwiftUI: переменная @State никогда не обновляется из @Published
Я пытаюсь вызвать предупреждение, когда в модели возникает ошибка, но оно никогда не обновляется, чтобы показать предупреждение:
Вот моя реализация в представлении:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel
@State var showAlert = false
init() {
viewModel = ViewModel()
showAlert = viewModel.showAlert
}
var body: some View {
NavigationView {
Text("Hello, world!")
.padding()
}
.alert(isPresented: $showAlert) {
Alert(title: Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
}
Вот мои модели:
class ViewModel: ObservableObject {
@Published var showAlert = false
var cancellables = Set<AnyCancellable>()
init() {
DoSomething.shared.showAlert.sink { _ in
print("got new Value")
} receiveValue: {[weak self] value in
print("value")
self?.showAlert = value
}.store(in: &cancellables)
}
}
class DoSomething {
let showAlert = PassthroughSubject<Bool, Never>()
static let shared = DoSomething()
private init() {
checkToShowAlert()
}
func checkToShowAlert() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) { [weak self] in
print("change value")
self?.showAlert.send(true)
}
}
}
Любой из вас знает, почему
showAlert
переменная никогда не обновляется?
Я буду очень признателен за вашу помощь
2 ответа
В вашем текущем коде вы устанавливаете
ContentView
's к 's в этот момент времени :
init() {
viewModel = ViewModel()
showAlert = viewModel.showAlert //<-- assignment at the time of init
}
Это означает, что это
false
на момент назначения. Потому что это просто назначение другому
Bool
, нет механизма для обновления, если
ViewModel
х
showAlert
изменения.
Самое простое решение - избавиться от
@State
переменная и наблюдать за
@Published
недвижимость напрямую:
struct ContentView: View {
@ObservedObject var viewModel: ViewModel = ViewModel()
var body: some View {
NavigationView {
Text("Hello, world!")
.padding()
}
.alert(isPresented: $viewModel.showAlert) {
Alert(title: Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
}
Избавьтесь от объекта модели представления, это основная проблема. Мы не используем их в SwiftUI. Мы используем структуру View для данных представления и
@State
а также
@Binding
обертки свойств, чтобы структура вела себя как объект, поэтому вам нужно сначала изучить это.
Также я не думаю, что вам нужен Combine для того, что вы пытаетесь сделать, потому что вы ничего не комбинируете, используя
combineLatest
и т. д., но когда мы используем его в SwiftUI, мы не используем
sink
или же
store
, вместо этого мы
assign
конец трубопровода к
@Published
.
Пример:
struct ContentView: View {
@State var isPresented = false
var body: some View {
NavigationView {
VStack{
Text("Hello, world!")
.padding()
Button("Show Alert") {
showAlert()
}
}
}
.alert(isPresented: $isPresented) {
Alert(title:Text("This works"),
message: Text("Hello"),
dismissButton: .default(Text("got it"))
)}
}
func showAlert() {
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
isPresented = true
}
}
}