SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
30.11.2024

Aula 187: Técnicas Avançadas de Core Data

Nesta aula, vamos explorar algumas técnicas avançadas para trabalhar com Core Data em Swift. Core Data é um poderoso framework para gerenciar os objetos da camada de modelo em sua aplicação. Enquanto operações básicas de CRUD são essenciais, dominar técnicas avançadas pode melhorar significativamente o desempenho e a escalabilidade do seu aplicativo.

1. Usando Requisições de Busca com Predicados

Requisições de busca permitem que você recupere objetos do armazenamento persistente. Ao usar predicados, você pode refinar suas consultas de forma eficaz.

import CoreData

// Supondo que temos uma entidade chamada "Pessoa"
func buscarPessoas(comNome nome: String, contexto: NSManagedObjectContext) -> [Pessoa]? {
    let requisicaoBusca: NSFetchRequest<Pessoa> = Pessoa.fetchRequest()
    requisicaoBusca.predicate = NSPredicate(format: "nome == %@", nome)

    do {
        let resultados = try contexto.fetch(requisicaoBusca)
        return resultados
    } catch {
        print("Falha ao buscar pessoas: \(error.localizedDescription)")
        return nil
    }
}

Neste exemplo, criamos uma requisicaoBusca para a entidade Pessoa e filtramos os resultados com base no atributo nome usando um predicado.

2. Atualizações em Lote para Melhor Desempenho

Core Data permite atualizações em lote, o que pode melhorar o desempenho ao evitar a necessidade de carregar e armazenar objetos em cache.

func atualizarIdadePessoas(contexto: NSManagedObjectContext, novaIdade: Int16) {
    let requisicaoBusca: NSFetchRequest<Pessoa> = Pessoa.fetchRequest()
    let atualizacaoEmLote = NSBatchUpdateRequest(entityName: "Pessoa")
    atualizacaoEmLote.predicate = NSPredicate(format: "idade < %@", NSNumber(value: novaIdade))
    atualizacaoEmLote.propertiesToUpdate = ["idade": novaIdade]
    atualizacaoEmLote.resultType = .updatedObjectIDsResultType

    do {
        let resultado = try contexto.execute(atualizacaoEmLote) as? NSBatchUpdateResult
        print("Atualizadas \(resultado?.result ?? 0) pessoas.")
    } catch {
        print("Falha na atualização em lote: \(error.localizedDescription)")
    }
}

Neste exemplo, criamos uma requisição de atualização em lote que atualiza a idade de todos os objetos Pessoa onde a idade atual é menor que novaIdade.

3. Usando Contextos em Segundo Plano para Tarefas de Longa Duração

Executar tarefas de longa duração no contexto principal pode bloquear sua interface do usuário. Usar um contexto em segundo plano pode ajudar a mitigar isso.

func realizarBuscaEmSegundoPlano() {
    let contextoBackground = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    contextoBackground.parent = persistentContainer.viewContext

    contextoBackground.perform {
        let requisicaoBusca: NSFetchRequest<Pessoa> = Pessoa.fetchRequest()

        do {
            let resultados = try contextoBackground.fetch(requisicaoBusca)
            print("Buscadas \(resultados.count) pessoas em segundo plano.")
        } catch {
            print("Falha ao buscar em segundo plano: \(error.localizedDescription)")
        }
    }
}

Usar perform garante que a requisição de busca seja executada no contexto em segundo plano sem bloquear o thread principal.

4. Mesclando Alterações do Contexto em Segundo Plano

Ao trabalhar com múltiplos contextos, especialmente em segundo plano, mesclar alterações corretamente é crucial para manter seus dados consistentes.

func mesclarAlteracoes(notificacao: Notification) {
    guard let contexto = notificacao.object as? NSManagedObjectContext else { return }

    // Buscar o contexto principal
    let contextoPrincipal = persistentContainer.viewContext
    contextoPrincipal.perform {
        contextoPrincipal.mergeChanges(fromContextDidSave: notificacao)
        print("Mescladas as alterações do contexto em segundo plano.")
    }
}

// Adiciona um observador para notificações de salvamento do contexto em segundo plano
NotificationCenter.default.addObserver(forName: NSManagedObjectContext.didSaveNotification, object: contextoBackground, queue: nil) { notificacao in
    self.mesclarAlteracoes(notificacao: notificacao)
}

Este exemplo demonstra como observar notificações de salvamento e mesclar alterações de um contexto em segundo plano de volta no contexto principal.

5. Usando o Controller de Resultados Buscados para Integração com a Tabela

A classe NSFetchedResultsController é projetada para gerenciar de forma eficiente os resultados de uma requisição de busca do Core Data.

class PessoaListViewController: UITableViewController, NSFetchedResultsControllerDelegate {
    var controllerDeResultadosBuscados: NSFetchedResultsController<Pessoa>!

    override func viewDidLoad() {
        super.viewDidLoad()
        configurarControllerDeResultadosBuscados()
    }

    func configurarControllerDeResultadosBuscados() {
        let requisicaoBusca: NSFetchRequest<Pessoa> = Pessoa.fetchRequest()
        requisicaoBusca.sortDescriptors = [NSSortDescriptor(key: "nome", ascending: true)]

        controllerDeResultadosBuscados = NSFetchedResultsController(fetchRequest: requisicaoBusca,
                                                                    managedObjectContext: persistentContainer.viewContext,
                                                                    sectionNameKeyPath: nil,
                                                                    cacheName: nil)
        controllerDeResultadosBuscados.delegate = self

        do {
            try controllerDeResultadosBuscados.performFetch()
            tableView.reloadData()
        } catch {
            print("Falha ao buscar pessoas: \(error.localizedDescription)")
        }
    }

    // Implementar métodos do delegate para lidar com atualizações
    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.beginUpdates()
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }

    // Implementar outros métodos do delegate conforme necessário para atualizações de linhas...
}

O NSFetchedResultsController rastreia automaticamente as alterações nos dados e notifica o delegate, facilitando a manutenção da sua interface do usuário em sincronia com seus dados.

Conclusão

Nesta aula, cobrimos várias técnicas avançadas de Core Data que aprimoram sua capacidade de gerenciar e manipular dados em suas aplicações Swift. Ao aproveitar requisições de busca com predicados, atualizações em lote, contextos em segundo plano, mesclagem de alterações e utilizando controllers de resultados buscados, você pode construir aplicações robustas e responsivas. Compreender essas técnicas permitirá que você aproveite todo o poder do Core Data em seus projetos. Boas codificações!

Video

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

Thank you for voting!