2017-01-19 20 views
0

Я пытаюсь отфильтровать свой объект NSFetchedResultsController при поиске в таблицеView. Я пробовал с NSPredicate, но я не могу заставить его работать.
Я использую Swift 3.
Это мой код:iOS Swift - использовать данные сердечника предиката для фильтрации таблицыView

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 файл, он возвращает массив с NSManagedObject и NSFetchedResultsController:

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 
} 

Ну, нет никакой ошибки, но поиск всегда возвращается пустым, я думаю, что мое выражение в предикате неверно: NSPredicate(format: "razon_social contains[cd] %@", buscar)
Кроме того, я хочу сделать это нечувствительным, что достигается с помощью ANY razon_social ..?

ответ

0

Я получил небольшую помощь несколько дней назад, и я собираюсь поделиться им с вами.

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 
} 

Файл: Clientes + 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($0) } 
     return letra[0].uppercased() 
    } 
} 

ВАЖНО !! Файл: Cliente.swift.
Объект класса «Клиент» с функцией «convertir()». Этот класс работает как объект, с которым заполняется «aFiltrados», и для фильтрации объекта CoreData требуется преобразовать его в этот объект «Cliente».

import UIKit 

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

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

Ваш предикат выглядит действительным для меня. «c» для caseInsensitive и «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)") 
} 

Вы должны попытаться проверить, если ваши данные правильно, удалив предикат, например, чтобы увидеть полные результаты, и так далее.