簡體   English   中英

SwiftUI:@State 變量永遠不會從@Published 更新

[英]SwiftUI: @State variable never get updated from @Published

我試圖在 model 出現錯誤時觸發警報,但它從未更新以顯示警報:

這是我在視圖中的實現:

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變量嗎?

我會非常感謝你的幫助

在您當前的代碼中,您在該時間點將ContentViewshowAlert設置為ViewModelshowAlert

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

意思是,在分配時它是false的。 因為它只是一個Bool被分配給另一個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"))
        )}
    }
}

擺脫視圖model object,這是主要問題。 我們不使用 SwiftUI 中的那些。 我們將 View 結構用於視圖數據,並使用@State@Binding屬性包裝器使該結構的行為類似於 object,因此您需要先了解這一點。

另外,我認為您不需要為您嘗試做的事情使用 Combine ,因為您沒有使用combineLatest等組合任何東西,但是當我們在 SwiftUI 中使用它時,我們不使用sinkstore ,而是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
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM