1

我试图在模型中出现错误时触发警报,但它永远不会更新以显示警报:

这是我在视图中的实现:

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它永远不会更新的变量吗?

我会非常感谢你的帮助

4

2 回答 2

1

在您当前的代码中,您在那个时间点将'设置为ContentView' :showAlertViewModelshowAlert

init() {
  viewModel = ViewModel()
  showAlert = viewModel.showAlert //<-- assignment at the time of init
}

意思是,它是false在分配的时间。因为它只是Bool分配给 another ,所以如果's发生变化Bool,没有机制可以保持更新。ViewModelshowAlert

最简单的解决方案是摆脱你的@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"))
        )}
    }
}
于 2022-02-05T02:15:11.677 回答
0

摆脱视图模型对象,这是主要问题。我们不在 SwiftUI 中使用它们。我们将 View 结构用于视图数据,使用@Stateand@Binding属性包装器使结构表现得像一个对象,因此您需要先了解这一点。

另外,我认为您不需要使用 Combine 来完成您尝试做的事情,因为您没有使用combineLatestetc 组合任何东西,但是当我们在 SwiftUI 中使用它时,我们不使用sinkor 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
        }
    }
}
于 2022-02-05T23:40:47.310 回答