Lição: 75: Fluxo de Dados no SwiftUI
O SwiftUI é um framework poderoso para construir interfaces de usuário em todas as plataformas da Apple. Um dos conceitos mais importantes a entender no SwiftUI é o fluxo de dados, que determina como os dados são passados e gerenciados dentro do seu aplicativo. Nesta aula, vamos explorar as principais maneiras de gerenciar o fluxo de dados no SwiftUI: @State
, @Binding
, @ObservedObject
e @EnvironmentObject
.
1. @State
@State
é usado para gerenciar o estado simples dentro de uma única view. Ele permite criar um pedaço de estado mutável em uma view, que pode ser atualizado e observado.
import SwiftUI
struct ContadorView: View {
@State private var contador = 0
var body: some View {
VStack {
Text("Contador: \(contador)")
.font(.largeTitle)
Button(action: {
self.contador += 1
}) {
Text("Incrementar")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.padding()
}
}
struct ContadorView_Previews: PreviewProvider {
static var previews: some View {
ContadorView()
}
}
Neste exemplo, ao tocar no botão "Incrementar", o valor do contador exibido na tela aumenta.
2. @Binding
@Binding
é utilizado para criar uma conexão de mão dupla entre uma view pai e uma view filho. Isso permite passar um valor de um pai e permitir que o filho o modifique.
import SwiftUI
struct ViewPai: View {
@State private var nome: String = "Mundo"
var body: some View {
VStack {
Text("Olá, \(nome)!")
ViewFilho(nome: $nome)
}
.padding()
}
}
struct ViewFilho: View {
@Binding var nome: String
var body: some View {
TextField("Digite seu nome", text: $nome)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
}
}
struct ViewPai_Previews: PreviewProvider {
static var previews: some View {
ViewPai()
}
}
Neste caso, a ViewFilho
modifica o estado de nome
na ViewPai
, demonstrando uma relação de binding entre as duas views.
3. @ObservedObject
@ObservedObject
é usado para observar um objeto de modelo externo em busca de mudanças. Quando o modelo muda, a view é atualizada automaticamente para refletir o novo estado. Isso é particularmente útil para gerenciar estados que são compartilhados entre várias views.
import SwiftUI
import Combine
class ModeloTimer: ObservableObject {
@Published var tempoRestante = 60
private var timer: AnyCancellable?
func iniciarTimer() {
timer = Timer.publish(every: 1, on: .main, in: .common)
.autoconnect()
.sink { [weak self] _ in
if self?.tempoRestante ?? 0 > 0 {
self?.tempoRestante -= 1
} else {
self?.timer?.cancel()
}
}
}
}
struct ViewTimer: View {
@ObservedObject var modeloTimer = ModeloTimer()
var body: some View {
VStack {
Text("Tempo Restante: \(modeloTimer.tempoRestante)")
.font(.largeTitle)
Button(action: {
modeloTimer.iniciarTimer()
}) {
Text("Iniciar Timer")
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(10)
}
}
.padding()
}
}
struct ViewTimer_Previews: PreviewProvider {
static var previews: some View {
ViewTimer()
}
}
Neste exemplo, o timer faz a contagem regressiva a partir de 60 segundos, e a view é atualizada a cada segundo à medida que tempoRestante
muda.
4. @EnvironmentObject
@EnvironmentObject
é usado para injetar dados de uma view pai em suas views filhas, fornecendo uma fonte de dados compartilhada em toda a hierarquia de views.
import SwiftUI
class ConfiguracoesUsuario: ObservableObject {
@Published var nomeUsuario: String = "Convidado"
}
struct ViewPrincipal: View {
@EnvironmentObject var configuracoesUsuario: ConfiguracoesUsuario
var body: some View {
VStack {
Text("Nome de Usuário: \(configuracoesUsuario.nomeUsuario)")
ViewFilho()
}
.padding()
}
}
struct ViewFilho: View {
@EnvironmentObject var configuracoesUsuario: ConfiguracoesUsuario
var body: some View {
TextField("Digite seu nome de usuário", text: $configuracoesUsuario.nomeUsuario)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
}
}
@main
struct MeuApp: App {
var configuracoesUsuario = ConfiguracoesUsuario()
var body: some Scene {
WindowGroup {
ViewPrincipal()
.environmentObject(configuracoesUsuario)
}
}
}
Neste caso, o objeto ConfiguracoesUsuario
é injetado na hierarquia de views, permitindo que tanto ViewPrincipal
quanto ViewFilho
acessem e modifiquem a propriedade nomeUsuario
de forma integrada.
Conclusão
Entender o fluxo de dados no SwiftUI é essencial para construir aplicativos dinâmicos e interativos. Seja utilizando @State
, @Binding
, @ObservedObject
ou @EnvironmentObject
, cada um tem seu próprio propósito e casos de uso. Ao aproveitar esses wrappers de propriedades, você pode criar interfaces de usuário eficientes e responsivas que refletem as mudanças nos dados com facilidade.