iOS Swift - 使用谓词核心数据过滤一个tableView

iOS Swift - Use predicate core data to filter a tableView

我在 tableView 中搜索时试图过滤我的 NSFetchedResultsController 对象。我试过 NSPredicate 但我无法让它工作。
我正在使用 Swift 3.
这是我的代码:

func filtrarContenido(searchText: String) {
    let buscar = searchText.lowercased()

    let nombrePredicate = NSPredicate(format: "nombre_comercial contains[cd] %@", buscar)
    let razSocialPredicate = NSPredicate(format: "razon_social contains[cd] %@", buscar)
    let predicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.or, subpredicates: [nombrePredicate, razSocialPredicate])

    let respuesta = self.funcCoreData.obtenerResultadosFiltrados(entidad: "Clientes", orden: "nombre_comercial", ascendente: true, predicate: predicate)
    self.resultadosFiltrados = respuesta[1] as! NSFetchedResultsController<NSManagedObject>

    do {
        try self.resultadosFiltrados.performFetch()
    } catch {
        print(" \(error)")
    }
}

这是 FuncCoreData 文件中的函数,它 return 是一个包含 NSManagedObjectNSFetchedResultsController 的数组:

func obtenerResultadosFiltrados(entidad: String, orden: String, ascendente: Bool, predicate: NSPredicate) -> [AnyObject] {
    let appDelegate = UIApplication.shared.delegate as? AppDelegate
    let context = appDelegate?.persistentContainer.viewContext

    let objeto = NSFetchRequest<NSManagedObject>(entityName: entidad)
    let ordenacion = NSSortDescriptor(key: orden, ascending: ascendente)
    objeto.sortDescriptors = [ordenacion]
    objeto.predicate = predicate

    print("OBJETO: ", objeto)

    let recorrerResultados = NSFetchedResultsController<NSManagedObject>(fetchRequest: objeto, managedObjectContext: context!, sectionNameKeyPath: "seccionLetra", cacheName: nil)

    var array = [AnyObject]()
    array.append(objeto)
    array.append(recorrerResultados)

    return array
}

嗯,没有得到任何错误,但搜索总是return空的,我认为我在谓词中的表达不正确: NSPredicate(format: "razon_social contains[cd] %@", buscar)
此外,我想让它 insensitive,这是通过 ANY razon_social .. ?

实现的

你的谓词对我来说似乎有效。 "c" 用于不区分大小写,"d" 用于重音符号和类似的东西。

我尝试建立一个与您的项目类似的项目,其中包含一个名为 Clientes 的实体,包含 3 个名为 nombre_comercial、razon_social 和 seccionLetra 的可选字符串,使用了您的函数,它似乎正在工作。

我已经尝试在您的 performFetch() 之后立即打印结果并得到正确的结果。

do {
    try resultadosFiltrados.performFetch()
    if let results = resultadosFiltrados.fetchedObjects as? [Clientes] {
        print ("results.count \(results.count)")
        for cliente in results {
            print("nombre comercial \(cliente.nombre_comercial! )")
        }
     }            
} catch {
    print(" \(error)")
}

您应该尝试检查您的数据是否正确,例如通过删除谓词,查看完整的结果等。

前些日子在大家的帮助下搞定了,分享给大家。

var estaBuscando = false
let funcCoreData = FuncCoreData()
var resultados: NSFetchedResultsController<NSManagedObject> = NSFetchedResultsController()
var resultadosFiltrados: NSFetchedResultsController<NSManagedObject> = NSFetchedResultsController()
var objeto: NSFetchRequest<NSManagedObject> = NSFetchRequest()
var aFiltrados = [Cliente]()

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    let respuesta = self.funcCoreData.obtenerResultados(entidad: "Clientes", orden: "nombre_comercial", ascendente: true)
    self.objeto = respuesta[0] as! NSFetchRequest<NSManagedObject>
    self.resultados = respuesta[1] as! NSFetchedResultsController<NSManagedObject>
    do {
        try self.resultados.performFetch()
        self.pintarSecciones()
    } catch {
        print(" \(error)")
    }
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell

    if estaBuscando {
        let obj2 = self.aFiltrados[indexPath.item]
        cell.codigo.text = obj2.codigo
        cell.titulo.text = obj2.nombre
        cell.subtitulo.text = obj2.razonSocial
        return cell;
    } else {
        if let obj = self.resultados.object(at: indexPath) as? Clientes {
            cell.codigo.text = obj.codigo!
            cell.titulo.text = obj.nombre_comercial!
            cell.subtitulo.text = obj.razon_social!
        }
    }
    return cell
}

func filtrarContenido(searchText: String) {
    let buscar = searchText.lowercased()

    let p1 = NSPredicate(format: "nombre_comercial contains[cd] %@", buscar)
    let p2 = NSPredicate(format: "razon_social contains[cd] %@", buscar)
    let predicate = NSCompoundPredicate(type: NSCompoundPredicate.LogicalType.or, subpredicates: [p1, p2])
    let respuesta = self.funcCoreData.obtenerResultadosFiltrados(entidad: "Clientes", orden: "nombre_comercial", ascendente: true, predicate: predicate)
    self.resultadosFiltrados = respuesta[1] as! NSFetchedResultsController<NSManagedObject>

    do {
        try self.resultadosFiltrados.performFetch()
        self.aFiltrados = [Cliente]() // limpiar listado
        // convertir cada resultado obtenido al modelo Cliente
        for cli in self.resultadosFiltrados.fetchedObjects as! [Clientes] {
            let cliente = Cliente()
            cliente.convertir(cliente: cli)
            self.aFiltrados.append(cliente)
        }
    } catch {
        print(" Filtrar clientes \(error)")
    }
}

func searchDisplayController(_ controller: UISearchDisplayController, shouldReloadTableForSearch searchString: String?) -> Bool {
    self.filtrarContenido(searchText: searchString!)
    return true
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if(searchText.isEmpty) {
        estaBuscando = false
    } else {
        estaBuscando = true
    }
    self.filtrarContenido(searchText: searchText)
    self.tableView.reloadData()
}

文件:FuncCoreData.swift

func obtenerResultadosFiltrados(entidad: String, orden: String, ascendente: Bool, predicate: NSPredicate) -> [AnyObject] {
    let appDelegate = UIApplication.shared.delegate as? AppDelegate
    let context = appDelegate?.persistentContainer.viewContext
    let objeto = recorrerObjeto(entidad: entidad, orden: orden, ascendente: ascendente)
    objeto.predicate = predicate
    let recorrerResultados = NSFetchedResultsController<NSManagedObject>(fetchRequest: objeto, managedObjectContext: context!, sectionNameKeyPath: "seccionLetra", cacheName: nil)

    var array = [AnyObject]()
    array.append(objeto)
    array.append(recorrerResultados)

    return array
}

func obtenerResultados(entidad: String, orden: String, ascendente: Bool) -> [AnyObject] {
    let appDelegate = UIApplication.shared.delegate as? AppDelegate
    let context = appDelegate?.persistentContainer.viewContext
    let objeto = recorrerObjeto(entidad: entidad, orden: orden, ascendente: ascendente)
    let recorrerResultados = NSFetchedResultsController<NSManagedObject>(fetchRequest: objeto, managedObjectContext: context!, sectionNameKeyPath: "seccionLetra", cacheName: nil)

    var array = [AnyObject]()
    array.append(objeto)
    array.append(recorrerResultados)

    return array
}

func recorrerObjeto(entidad: String, orden: String, ascendente: Bool) -> NSFetchRequest<NSManagedObject> {
    let objeto = NSFetchRequest<NSManagedObject>(entityName: entidad)
    let ordenacion = NSSortDescriptor(key: orden, ascending: ascendente, selector: #selector(NSString.caseInsensitiveCompare))
    objeto.sortDescriptors = [ordenacion]
    return objeto
}

文件:客户+CoreDataProperties.swift

import Foundation
import CoreData
extension Clientes {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Clientes> {
        return NSFetchRequest<Clientes>(entityName: "Clientes");
    }

    @NSManaged public var cif_dni: String?
    @NSManaged public var codigo: String?
    @NSManaged public var domicilio: String?
    ...

    var seccionLetra: String? {
        let letra = nombre_comercial!.characters.map { String([=12=]) }
        return letra[0].uppercased()
    }
}

重要!! 文件:Cliente.swift.
具有函数 'convertir()' 的对象 class 'Cliente'。 这个 class 就像一个填充了 'aFiltrados' 的对象,要过滤一个 CoreData 对象需要将它转换成这个对象 'Cliente'.

import UIKit

class Cliente {
    var codigo = ""
    var nombre = ""
    ...
    ...

    func convertir(cliente: Clientes) {
        codigo = cliente.cif_dni!
        nombre = cliente.nombre_comercial!
        ...
        ...
    }
}