Não tenho certeza se é um bom conceito, mas vamos começar por aqui.
Tenho uma visão simples:
struct InAppPurchaseView: View {
private let viewModel = InAppPurchaseViewModel()
var body: some View {
VStack {
if !viewModel.currentProgressInfo.isEmpty {
Text(viewModel.currentProgressInfo) // here it relies on the value from viewModel and should update every time when it changes
}
}
}
}
@Observable
class InAppPurchaseViewModel {
private let transactionObserver = TransactionObserver.shared
@Binding var currentProgressInfo: String
// here is the question❓
// How to bind here property from within transactionObserver?
}
@Observable
class TransactionObserver: NSObject, SKProductsRequestDelegate, SKPaymentTransactionObserver {
static let shared = TransactionObserver()
var currentProgressInfo = ""
// here is the code that updates currentProgressInfo depending on the needs.
}
Exemplo de uso?
Na outra visão, suponha que eu tenha (totalmente abstrato) duas instâncias próximas uma da outra. Cada uma tem seu próprio viewModel
struct StartView: View {
var body: some View {
VStack {
InAppPurchaseView() // here it need to be updated
InAppPurchaseView() // here it need to be updated THE SAME WAY.
}
}
}
Uma simples ação tomada em uma das situações acima InAppPurchaseView
deve impactar e atualizar outra com o mesmo efeito.
@Observable
s rastreia alterações usando os getters/setters de suas propriedades (a@Observable
macro insere algum código nos getters/setters para fazer esse rastreamento). Enquanto um getter/setter for chamado durante a avaliação de uma viewbody
, o SwiftUI trata isso como uma dependência da view e atualizará a view quando essa propriedade for definida novamente.O corpo da sua visualização chama o getter de
InAppPurchaseViewModel.currentProgressInfo
, mas na verdade você querTransactionObserver.currentProgressInfo
que ele seja uma dependência da visualização, então você pode simplesmente fazer com que o getter do primeiro chame o getter do último.Em qualquer caso,
InAppPurchaseViewModel.currentProgressInfo
não deve ser uma propriedade armazenada, porque então você acabaria com múltiplas fontes de verdade.Nota lateral:
viewModel
inInAppPurchaseView
deve ser um@State
, e ter umashared
propriedade não é seguro para concorrência. Eu isolariashared
para@MainActor
, e isolaria toda aInAppPurchaseViewModel
classe para@MainActor
.