Observei um padrão estranho ao usar @ObservedObject
e @Published
.
Eu o injeto dentro de uma SwiftUI
visualização, mas a visualização parece atualizar antes da mudança real do objeto.
Então meu @ObservedObject
não tem o valor correto quando verifico sua @Published
propriedade.
Se eu adicionar um didSet
com um , objectWillChange.send()
funciona como esperado.
Aqui está o código com o qual estou trabalhando:
class AuthManager: ObservableObject {
@Published public private(set) var user: User {
willSet { print("Will set") }
didSet { print("Did set") }
}
}
struct AuthView: View {
@ObservedObject var authManager: AuthManager
var body: some View {
let _ = Self._printChanges()
print("AuthManager user = \(authManager.user)")
return (
Text("AuthManager Test")
)
}
}
Quando atualizo meu objeto de usuário no AuthManager, recebo os logs na seguinte ordem:
Will set
AuthView: @self, @identity, _authManager
AuthManager user = xxx // <-- old version
Did set
O comportamento funciona como esperado se eu remover o @Published
e acionar o objectWillChange.send()
no didSet
.
Espero ter a nova versão quando a visualização for atualizada. Estou esquecendo de algo ou há algo que não entendi sobre ObservableObject
e @Published
?
Obrigado
O
objectWillChange
publicador de umObservableObject
sempre emite um novo evento nowillSet
manipulador:Veja a documentação oficial .
O comportamento que você observou a esse respeito é, portanto, normal.
Se você alterar um valor de uma
Published
propriedade, um novo processo de layout será planejado, mas não executado diretamente. Isso permite que todas as alterações sejam coletadas primeiro e aplicadas juntas no próximo processo de layout.Veja o exemplo a seguir, que foi ligeiramente modificado do seu código, e você verá que a saída está correta, conforme o esperado:
A saída após pressionar o botão será:
O que você não nos mostra no seu código é como você altera o
user
valor deAuthManager
.Há muitas coisas que podem causar o problema que você descreve. Por exemplo, se você não alterar o valor do thread principal. Observe como eu vinculei o
ContentViewModel
no meu exemplo aoMainActor
.Suas saídas de log também são incomuns. Alterar a
user
propriedade não deve causar uma mudança na identidade estrutural da view, a única saída de log que você deve realmente ver é:@self
e@identity
não deve ser incluído na saída do log.Esta saída indica, portanto, que você tem um problema na visualização pai, em outra visualização circundante
AuthView
ou na maneira como está alterando aPublished
propriedade.