SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
19.11.2024

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.

Video

Did you like this article? Rate it from 1 to 5:

Thank you for voting!