Estou tentando implementar o código de pesquisa no meu aplicativo para iPhone baseado em CoreData. Não tenho certeza de como proceder. O aplicativo já possui um NSFetchedResultsController com um predicado para recuperar os dados para o TableView primário. Quero ter certeza de que estou no caminho certo antes de alterar muito código. Estou confuso porque muitos dos exemplos são baseados em matriz, em vez de CoreData.
Aqui estão algumas perguntas:
Preciso ter um segundo NSFetchedResultsController que recupere apenas os itens correspondentes ou posso usar o mesmo que o TableView principal?
Se eu usar o mesmo, é tão simples quanto limpar o cache do FRC e alterar o predicado no método handleSearchForTerm: searchString? O predicado precisa conter o predicado inicial e os termos de pesquisa ou lembra que usou um predicado para recuperar dados em primeiro lugar?
Como faço para voltar aos resultados originais? Acabei de definir o predicado de pesquisa como nulo? Isso não mata o predicado original usado para recuperar os resultados do FRC em primeiro lugar?
Se alguém tiver algum exemplo de código usando a pesquisa com o FRC, eu agradeceria muito!
Respostas:
Na verdade, acabei de implementar isso em um dos meus projetos (sua pergunta e a outra resposta errada sugeriram o que fazer). Tentei a resposta de Sergio, mas tive problemas de exceção ao executar em um dispositivo.
Sim, você cria dois controladores de resultados de busca: um para a exibição normal e outro para a exibição da tabela do UISearchBar.
Se você usar apenas um FRC (NSFetchedResultsController), o UITableView original (não a exibição da tabela de pesquisa que está ativa durante a pesquisa) possivelmente terá retornos de chamada chamados durante a pesquisa e tente usar incorretamente a versão filtrada do seu FRC e você verá exceções lançado sobre o número incorreto de seções ou linhas em seções.
Aqui está o que eu fiz: Eu tenho dois FRCs disponíveis como propriedades fetchedResultsController e searchFetchedResultsController. O searchFetchedResultsController não deve ser usado, a menos que haja uma pesquisa (quando a pesquisa é cancelada, você pode ver abaixo que este objeto foi lançado). Todos os métodos UITableView devem descobrir em qual exibição de tabela ele consultará e de qual FRC aplicável obter as informações. Os métodos de delegação do FRC também devem descobrir qual tableView atualizar.
É surpreendente quanto disso é um código padrão.
Bits relevantes do arquivo de cabeçalho:
bits relevantes do arquivo de implementação:
Criei um método útil para recuperar o FRC correto ao trabalhar com todos os métodos UITableViewDelegate / DataSource:
Delegar métodos para a barra de pesquisa:
certifique-se de usar a exibição de tabela correta ao obter atualizações dos métodos de delegação do FRC:
Outras informações de exibição:
Código de criação FRC:
fonte
searchFetchedResultsController
paranil
sempre que o texto da pesquisa for alterado.cellForRowAtIndexPath
caso, você não deveria obter o celularself.tableView
como alguém apontado nesta pergunta do SO? Se você não fizer isso, a célula personalizada não será exibida.Alguns comentaram que isso pode ser feito com um único
NSFetchedResultsController
. Foi o que fiz e aqui estão os detalhes. Esta solução pressupõe que você deseja filtrar a tabela e manter todos os outros aspectos (ordem de classificação, layout da célula etc.) dos resultados da pesquisa.Primeiro, defina duas propriedades em sua
UITableViewController
subclasse (com o @synthesize e o dealloc, se aplicável):Segundo, inicialize a barra de pesquisa no
viewDidLoad:
método da suaUITableViewController
subclasse:Terceiro, implemente os
UISearchDisplayController
métodos delegados como este:Por fim, no
fetchedResultsController
método, altere aNSPredicate
dependência seself.searchString
for definida:fonte
Levei algumas tentativas para fazer isso funcionar ...
Minha chave para entender foi perceber que existem dois tableViews em funcionamento aqui. Um gerenciado pelo meu viewcontroller e outro gerenciado pelo searchviewcontroller e, em seguida, pude testar para ver qual está ativo e fazer a coisa certa. A documentação também foi útil:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UISearchDisplayController_Class/Reference/Reference.html
Aqui está o que eu fiz -
Adicionado o sinalizador searchIsActive:
Adicionada a síntese no arquivo de implementação.
Em seguida, adicionei esses métodos para a pesquisa:
Em seguida, em controllerWillChangeContent:
And controllerDidChangeContent:
E exclua o cache ao redefinir o predicado.
Espero que isto ajude.
fonte
if ( [self.tableView isEqual:self.searchDisplayController.searchResultsTableView] ) { ... }
Enfrentei a mesma tarefa e encontrei A MANEIRA MAIS SIMPLES POSSÍVEL para resolvê-la. Resumidamente: você precisa definir mais um método, muito semelhante a
-fetchedResultsController
um predicado composto personalizado.No meu caso pessoal, minha
-fetchedResultsController
aparência é assim:Como você pode ver, estou buscando clientes de uma agência filtrada por
agency.server_id
predicado. Como resultado, também estou recuperando meu conteúdo em umtableView
(tudo relacionado à implementaçãotableView
e aofetchedResultsController
código). Para implementarsearchField
, estou definindo umUISearchBarDelegate
método delegado. Estou ativando-o com o método de pesquisa, digamos-reloadTableView
:e, claro, a definição de
-reloadTableView
:Esse monte de código é muito semelhante ao primeiro, "padrão",
-fetchedResultsController
MAS dentro da instrução if-else aqui é:+andPredicateWithSubpredicates:
- usando esse método, podemos definir um predicado para salvar os resultados da nossa primeira busca principal notableView
+orPredicateWithSubpredicates
- usando esse método, estamos filtrando a busca existente pela consulta de pesquisa desearchBar
No final, estou definindo uma matriz de predicados como predicado composto para essa busca em particular. E para predicados necessários, OU para opcional.
E isso é tudo! Você não precisa implementar mais nada. Feliz codificação!
fonte
Você está usando uma pesquisa ao vivo?
Se você NÃO é, provavelmente deseja uma matriz (ou um NSFetchedResultsController) com as pesquisas anteriores que você usou, quando o usuário pressiona "pesquisar", você diz ao FetchedResults para alterar seu predicado.
De qualquer forma, você precisará reconstruir seus FetchedResults sempre. Eu recomendo usar apenas um NSFetchedResultsController, pois você precisará duplicar muito seu código e não precisará desperdiçar memória em algo que não está mostrando.
Apenas verifique se você tem uma variável "searchParameters" do NSString e se o seu método FetchedResults a reconstrói conforme necessário, usando os parâmetros de pesquisa, se disponíveis, você deve:
Aqui está um código simples:
fonte
Swift 3.0, UISearchController, NSFetchedResultsController e Core Data
Este código funcionará no Swift 3.0 com
Core Data
! Você precisará de um único método delegado e de algumas linhas de código para filtrar e pesquisar objetos do modelo. Nada será necessário se você tiver implementado todosFRC
e seusdelegate
métodos, bem comosearchController
.O
UISearchResultsUpdating
método de protocoloÉ isso aí! Espero que ajude você! obrigado
fonte
SWIFT 3.0
Use um textField, o UISearchDisplayController está obsoleto no iOS 8, você precisaria usar um UISearchController. Em vez de lidar com o Search Controller, por que você não cria seu próprio mecanismo de pesquisa? Você pode personalizá-lo mais e ter mais controle sobre ele, e não precisa se preocupar com a alteração e / ou descontinuação do SearchController.
Esse método que eu uso funciona muito bem e não requer muito código. No entanto, é necessário o uso de Dados Principais e a implementação do NSFetchedResultsController.
Primeiro, crie um TextField e registre-o com um método:
Em seguida, crie seu método textFieldDidChange, descrito no seletor quando o destino foi adicionado:
Em seguida, você deseja filtrar a lista no
filterList()
método usando o predicado NSPredicate ou NSCompound, se for mais complexo. No meu método filterList, estou filtrando com base no nome da entidade e no nome do objeto "subCategories" das entidades (um relacionamento de um para muitos).fonte
Eu acho que Luka tem uma abordagem melhor para isso. Veja LargeDataSetSample e seu motivo
Ele não usa
FetchedResultsController
, mas usa cache ao pesquisar, portanto, os resultados da pesquisa aparecem muito mais rapidamente quando o usuário digita mais no SearchBarEu usei a abordagem dele no meu aplicativo e funciona bem. Lembre-se também de que, se você deseja trabalhar com o objeto Model, torne o mais simples possível, consulte minha resposta sobre setPropertiesToFetch
fonte
Aqui está uma maneira de lidar com os resultados buscados com vários conjuntos de dados, simples e gerais o suficiente para serem aplicados em praticamente qualquer lugar. Simplesmente pegue seus principais resultados em uma matriz quando alguma condição estiver presente.
Consulte a matriz fazendo um loop através dela ou o que você desejar, a fim de criar um subconjunto de seus principais resultados buscados. E agora você pode usar o conjunto completo ou subconjunto quando alguma condição estiver presente.
fonte
Eu realmente gostei da abordagem de @Josh O'Connor, onde ele não usa a
UISearchController
. Este controlador ainda (Xcode 9) possui um bug de layout que muitos estão tentando solucionar.Voltei a usar um em
UISearchBar
vez de umUITextField
e funciona muito bem. Minha exigência para a pesquisa / filtro é produzir umNSPredicate
. Isso é passado para o FRC:...
Finalmente, conecte o SearchBar ao seu delegado.
Espero que isso ajude outros
fonte
Abordagem simples para filtrar o UITableView existente usando CoreData e que já está classificado como você deseja.
Isso literalmente também me 5 minutos para configurar e começar a trabalhar.
Eu já tinha um
UITableView
usoCoreData
preenchido com dados do iCloud e que tem interações bastante complicadas do usuário e não queria replicar tudo isso para aUISearchViewController
. Consegui simplesmente adicionar um predicado aoFetchRequest
já existente usado peloFetchResultsController
e que filtra os dados já classificados.fonte