Estoy tratando de implementar el código de búsqueda en mi aplicación para iPhone basada en CoreData. No estoy seguro de cómo proceder. La aplicación ya tiene un NSFetchedResultsController con un predicado para recuperar los datos para el TableView primario. Quiero asegurarme de que estoy en el camino correcto antes de cambiar demasiado código. Estoy confundido porque muchos de los ejemplos están basados en matrices en lugar de CoreData.
Aquí hay algunas preguntas:
¿Necesito tener un segundo NSFetchedResultsController que recupere solo los elementos coincidentes o puedo usar el mismo que el TableView primario?
Si uso el mismo, ¿es tan simple como borrar el caché de FRC y luego cambiar el predicado en el método handleSearchForTerm: searchString? ¿El predicado tiene que contener el predicado inicial así como los términos de búsqueda o recuerda que usó un predicado para recuperar datos en primer lugar?
¿Cómo vuelvo a los resultados originales? ¿Acabo de establecer el predicado de búsqueda en nulo? ¿No matará eso el predicado original que se usó para recuperar los resultados de FRC en primer lugar?
Si alguien tiene algún ejemplo de código usando la búsqueda con el FRC, ¡lo agradecería mucho!
Respuestas:
De hecho, acabo de implementar esto en uno de mis proyectos (su pregunta y la otra respuesta incorrecta insinuaron qué hacer). Intenté la respuesta de Sergio, pero tuve problemas de excepción cuando realmente se ejecuta en un dispositivo.
Sí, crea dos controladores de resultados de búsqueda: uno para la visualización normal y otro para la vista de tabla de UISearchBar.
Si solo usa un FRC (NSFetchedResultsController), entonces el UITableView original (no la vista de la tabla de búsqueda que está activa durante la búsqueda) posiblemente reciba devoluciones de llamada mientras está buscando e intente usar incorrectamente la versión filtrada de su FRC y verá excepciones arrojado sobre un número incorrecto de secciones o filas en secciones.
Esto es lo que hice: tengo dos FRC disponibles como propiedades fetchedResultsController y searchFetchedResultsController. SearchFetchedResultsController no debe usarse a menos que haya una búsqueda (cuando se cancela la búsqueda, puede ver a continuación que se libera este objeto). Todos los métodos UITableView deben determinar qué vista de tabla consultará y de qué FRC aplicable extraerá la información. Los métodos de delegado de FRC también deben determinar qué tableView actualizar.
Es sorprendente cuánto de esto es el código repetitivo.
Bits relevantes del archivo de encabezado:
bits relevantes del archivo de implementación:
Creé un método útil para recuperar el FRC correcto al trabajar con todos los métodos UITableViewDelegate / DataSource:
Delegar métodos para la barra de búsqueda:
asegúrese de utilizar la vista de tabla correcta al obtener actualizaciones de los métodos de delegado de FRC:
Otra información de la vista:
Código de creación de FRC:
fuente
searchFetchedResultsController
quenil
cada vez que cambia el texto de búsqueda.cellForRowAtIndexPath
, ¿no deberías obtener la celdaself.tableView
como alguien señalado en esta pregunta SO? Si no hace esto, la celda personalizada no se muestra.Algunos han comentado que esto se puede hacer con una sola
NSFetchedResultsController
. Eso es lo que hice, y aquí están los detalles. Esta solución supone que solo desea filtrar la tabla y mantener todos los demás aspectos (orden de clasificación, diseño de celda, etc.) de los resultados de búsqueda.Primero, defina dos propiedades en su
UITableViewController
subclase (con los @synthesize y dealloc apropiados, si corresponde):Segundo, inicialice la barra de búsqueda en el
viewDidLoad:
método de suUITableViewController
subclase:Tercero, implemente los
UISearchDisplayController
métodos delegados de esta manera:Finalmente, en el
fetchedResultsController
método cambia elNSPredicate
dependiente ifself.searchString
está definido:fuente
Me tomó algunos intentos hacer que esto funcionara ...
Mi clave para entender fue darme cuenta de que hay dos tableViews en el trabajo aquí. Uno administrado por mi viewcontroller y otro administrado por searchviewcontroller y luego pude probar para ver cuál está activo y hacer lo correcto. La documentación también fue útil:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UISearchDisplayController_Class/Reference/Reference.html
Esto es lo que hice.
Se agregó el indicador searchIsActive:
Se agregó la sintetización en el archivo de implementación.
Luego agregué estos métodos para buscar:
Luego, en controllerWillChangeContent:
Y controllerDidChangeContent:
Y elimine el caché al restablecer el predicado.
Espero que esto ayude.
fuente
if ( [self.tableView isEqual:self.searchDisplayController.searchResultsTableView] ) { ... }
Me enfrenté a la misma tarea y encontré EL MODO MÁS SENCILLO POSIBLE para resolverlo. En resumen: debe definir un método más, muy similar a
-fetchedResultsController
un predicado compuesto personalizado.En mi caso personal, mi
-fetchedResultsController
aspecto es el siguiente:Como puede ver, estoy buscando clientes de una agencia filtrada por
agency.server_id
predicado. Como resultado, también estoy recuperando mi contenido entableView
(todo lo relacionado con la implementacióntableView
y elfetchedResultsController
código es bastante estándar). Para implementarsearchField
estoy definiendo unUISearchBarDelegate
método delegado. Lo estoy activando con el método de búsqueda, por ejemplo-reloadTableView
:y, por supuesto, la definición de
-reloadTableView
:Este grupo de código es muy similar al primero, "estándar"
-fetchedResultsController
PERO dentro de la declaración if-else aquí es:+andPredicateWithSubpredicates:
- utilizando este método podemos establecer un predicado para guardar los resultados de nuestra primera búsqueda principal en eltableView
+orPredicateWithSubpredicates
- usando este método, estamos filtrando la búsqueda existente por búsqueda desearchBar
Al final, estoy configurando una matriz de predicados como un predicado compuesto para esta búsqueda en particular. Y para predicados requeridos, O para opcional.
¡Y eso es todo! No necesita implementar nada más. ¡Feliz codificación!
fuente
¿Estás usando una búsqueda en vivo?
Si NO lo está, probablemente desee una matriz (o un NSFetchedResultsController) con las búsquedas anteriores que utilizó, cuando el usuario presiona "buscar", le dice a sus FetchedResults que cambien su predicado.
De cualquier manera, deberá reconstruir sus FetchedResults cada vez. Recomiendo usar solo un NSFetchedResultsController, ya que tendrás que duplicar mucho tu código y no necesitas desperdiciar memoria en algo que no estás mostrando.
Solo asegúrese de tener una variable NSString "searchParameters" y su método FetchedResults la reconstruya según sea necesario, utilizando los parámetros de búsqueda si están disponibles, simplemente debe hacer:
Aquí hay un código simple:
fuente
Swift 3.0, UISearchController, NSFetchedResultsController y Core Data
Este código funcionará en Swift 3.0 con
Core Data
! Necesitará un único método de delegado y algunas líneas de código para filtrar y buscar objetos del modelo. No se necesitará nada si ha implementado todos los métodosFRC
y susdelegate
métodos, así como tambiénsearchController
.El
UISearchResultsUpdating
método de protocolo¡Eso es! Espero que te ayude! Gracias
fuente
SWIFT 3.0
Use un campo de texto, UISearchDisplayController está en desuso a partir de iOS 8, tendría que usar un UISearchController. En lugar de tratar con el controlador de búsqueda, ¿por qué no crea su propio mecanismo de búsqueda? Puede personalizarlo más y tener más control sobre él, y no tener que preocuparse de que SearchController cambie o sea desaprobado.
Este método que utilizo funciona muy bien y no requiere mucho código. Sin embargo, requiere que use Core Data e implemente NSFetchedResultsController.
Primero, cree un TextField y regístrelo con un método:
Luego cree su método textFieldDidChange, descrito en el selector cuando se agregó el objetivo:
Luego, desea filtrar la lista en el
filterList()
método usando NSPredicate o NSCompound predicate si es más complejo. En mi método filterList, estoy filtrando según el nombre de la entidad y el nombre del objeto "subCategories" de las entidades (una relación de uno a muchos).fuente
Creo que Luka tiene un mejor enfoque para esto. Ver LargeDataSetSample y su razón
No usa
FetchedResultsController
, pero usa caché cuando busca, por lo tanto, los resultados de búsqueda aparecen mucho más rápido cuando el usuario escribe más en SearchBarHe usado su enfoque en mi aplicación y funciona bien. Recuerde también que si desea trabajar con el objeto Modelo, hágalo lo más simple posible, vea mi respuesta sobre setPropertiesToFetch
fuente
Aquí hay una forma de manejar los resultados obtenidos con múltiples conjuntos de datos que es lo suficientemente simple y general como para aplicar en casi cualquier lugar. Simplemente tome sus resultados principales en una matriz cuando haya alguna condición presente.
Consulte la matriz recorriéndola o lo que desee para crear un subconjunto de sus principales resultados obtenidos. Y ahora puede usar el conjunto completo o el subconjunto cuando existe alguna condición.
fuente
Realmente me gustó el enfoque de @Josh O'Connor donde no usa a
UISearchController
. Este controlador todavía (Xcode 9) tiene un error de diseño que muchos están tratando de solucionar.Volví a usar un en
UISearchBar
lugar de unUITextField
, y funciona bastante bien. Mi requisito para la búsqueda / filtro es producir unNSPredicate
. Esto se pasa al FRC:...
Finalmente, conecte la barra de búsqueda a su delegado.
Espero que esto ayude a otros
fuente
Enfoque simple para filtrar UITableView existente utilizando CoreData y que ya está ordenado como desee.
Esto literalmente también me lleva 5 minutos para configurar y trabajar.
Tenía un
UITableView
uso existenteCoreData
lleno de datos de iCloud y que tiene interacciones de usuario bastante complicadas y no quería tener que replicar todo eso por unUISearchViewController
. Pude simplemente agregar un predicado al existenteFetchRequest
ya utilizado porFetchResultsController
y que filtra los datos ya ordenados.fuente