Middle
Alguma vez usou a biblioteca Combine nos seus projetos?
sobes.tech IA
Resposta da IA
Sim, já utilizei.
A principal aplicação do Combine nos meus projetos está relacionada com o processamento de eventos assíncronos, tais como:
- Requisições de rede: processamento de respostas de API, transformação de dados, tratamento de erros.
- Alterações nos elementos de UI: reação a ações do utilizador, alterações em campos de texto, deslizes.
- Processamento de dados locais: acompanhamento de alterações em bases de dados (por exemplo, Core Data), notificações do FileManager.
- Criação de fluxos de dados reativos na arquitetura MVVM para ligação entre a View e o ViewModel.
Vantagens do uso do Combine:
- Redução do volume de código e melhoria da sua legibilidade ao trabalhar com operações assíncronas.
- Gestão centralizada de erros e cancelamento de operações.
- Composição e transformação fáceis de fluxos de dados usando operadores.
- Integração nativa com frameworks da Apple (SwiftUI, Core Data, URLSession).
Exemplo de uso do Combine para uma requisição de rede:
import Combine
import Foundation
struct APIResult: Decodable {
let value: String
}
func fetchData(from url: URL) -> AnyPublisher<APIResult, Error> {
URLSession.shared.dataTaskPublisher(for: url)
.map(\data) // Extrai os dados do tuple (data, response)
.decode(type: APIResult.self, decoder: JSONDecoder()) // Decodifica os dados
.receive(on: DispatchQueue.main) // Muda para o thread principal para atualizar a UI
.eraseToAnyPublisher() // Remove o tipo específico para simplicidade
}
// Exemplo de subscrição
let cancellable = fetchData(from: URL(string: "https://api.example.com/data")!)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("Requisição concluída com sucesso")
case .failure(let error):
print("Erro na requisição: \(error.localizedDescription)")
}
}, receiveValue: { result in
print("Dados recebidos: \(result.value)")
})
// É necessário guardar a referência a cancellable para manter a assinatura ativa
Também utilizei o Combine para ligar propriedades no MVVM:
class ViewModel {
@Published var text: String = ""
@Published var isValid: Bool = false
private var cancellables = Set<AnyCancellable>()
init() {
$text
.map { $0.count > 0 } // Transforma o texto em valor booleano
.assign(to: &$isValid) // Atribui o resultado à propriedade isValid
}
}
class ViewController: UIViewController {
let textView = UITextField()
let validationLabel = UILabel()
let viewModel = ViewModel()
private var cancellables = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
// Ligação do UITextField ao ViewModel
NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: textView)
.compactMap { ($0.object as? UITextField)?.text }
.assign(to: \.text, on: viewModel) // Atribui o texto ao ViewModel
// Ligação do ViewModel ao UILabel
viewModel.$isValid
.map { $0 ? "Válido" : "Inválido" }
.assign(to: \.text, on: validationLabel) // Atribui o texto ao UILabel
.store(in: &cancellables) // Guarda a assinatura
}
}
A experiência com o Combine é positiva, pois simplifica bastante o trabalho com assíncronismo em comparação com abordagens mais antigas (closures, delegates) em cenários complexos.