Usando Predicate em Swift

93

Estou trabalhando no tutorial aqui (aprendendo Swift) para meu primeiro aplicativo: http://www.appcoda.com/search-bar-tutorial-ios7/

Estou preso nesta parte (código Objective-C):

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name contains[c]         %@", searchText];
    searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}

Alguém pode aconselhar como criar um equivalente para NSPredicate em Swift?

levitatejay
fonte

Respostas:

158

Esta é realmente apenas uma mudança de sintaxe. OK, então temos esta chamada de método:

[NSPredicate predicateWithFormat:@"name contains[c] %@", searchText];

No Swift, os construtores pulam a parte "blahWith ..." e apenas usam o nome da classe como uma função e vão direto para os argumentos, o que [NSPredicate predicateWithFormat: …]aconteceria NSPredicate(format: …). (Para outro exemplo, [NSArray arrayWithObject: …]seria NSArray(object: …). Este é um padrão regular em Swift.)

Portanto, agora só precisamos passar os argumentos para o construtor. Em Objective-C, os literais NSString se parecem @"", mas em Swift usamos apenas aspas para strings. Isso nos dá:

let resultPredicate = NSPredicate(format: "name contains[c] %@", searchText)

E, de fato, é exatamente disso que precisamos aqui.

(A propósito, você notará que algumas das outras respostas usam uma string de formato como "name contains[c] \(searchText)". Incorreto. Isso usa interpolação de string, que é diferente da formatação de predicado e geralmente não funciona para isso.)

Mandril
fonte
Obrigado. Você me salva um dia!
Hugo,
2
Para abordar a segunda linha do seu método, você pode usar o predicado como:searchResults = recipes.filter { resultPredicate.evaluateWithObject($0) }
Ben Packard
43

Trabalhando com predicado por um bom tempo. Aqui está minha conclusão (SWIFT)

//Customizable! (for me was just important if at least one)
request.fetchLimit = 1


//IF IS EQUAL

//1 OBJECT
request.predicate = NSPredicate(format: "name = %@", txtFieldName.text)

//ARRAY
request.predicate = NSPredicate(format: "name = %@ AND nickName = %@", argumentArray: [name, nickname])


// IF CONTAINS

//1 OBJECT
request.predicate = NSPredicate(format: "name contains[c] %@", txtFieldName.text)

//ARRAY
request.predicate = NSPredicate(format: "name contains[c] %@ AND nickName contains[c] %@", argumentArray: [name, nickname])
Jiří Zahálka
fonte
1
O que é igual a LIKE 'a%z'?
TomSawyer de
@ Jiří Zahálka O que significa solicitar ouvir?
Muju
28

Exemplo de como usar no swift 2.0

let dataSource = [
    "Domain CheckService",
    "IMEI check",
    "Compliant about service provider",
    "Compliant about TRA",
    "Enquires",
    "Suggestion",
    "SMS Spam",
    "Poor Coverage",
    "Help Salim"
]
let searchString = "Enq"
let predicate = NSPredicate(format: "SELF contains %@", searchString)
let searchDataSource = dataSource.filter { predicate.evaluateWithObject($0) }

Você obterá (playground)

insira a descrição da imagem aqui

gbk
fonte
E se ... Se eu tiver uma variedade de dicionários? Como faço para analisar para obter os dados?
Revathy Durairajan
1
@RevathyDurairajan você precisa de SELF.yourkeyname para filtrar a matriz de dicionários.
Pawan Rai
11

Você pode usar filtros disponíveis em swift para filtrar o conteúdo de um array em vez de usar um predicado como em Objective-C.

Um exemplo em Swift 4.0 é o seguinte:

var stringArray = ["foundation","coredata","coregraphics"]
stringArray = stringArray.filter { $0.contains("core") }

No exemplo acima, como cada elemento da matriz é uma string, você pode usar o containsmétodo para filtrar a matriz.

Se a matriz contiver objetos personalizados, as propriedades desse objeto podem ser usadas para filtrar os elementos de maneira semelhante.

Gurunath Sripad
fonte
6

Use o código abaixo:

 func filterContentForSearchText(searchText:NSString, scopes scope:NSString)
{
    //var searchText = ""

    var resultPredicate : NSPredicate = NSPredicate(format: "name contains[c]\(searchText)", nil)

    //var recipes : NSArray = NSArray()

    var searchResults = recipes.filteredArrayUsingPredicate(resultPredicate)
}
PREMKUMAR
fonte
1
Por alguma razão, escrever assim não funcionou para mim, no entanto, fazer let myPredicateString = "nome contém [c] (searchText)" e, em seguida, executar var resultPredicate: NSPredicate = NSPredicate (formato: myPredicateString) funcionou
AppHandwerker
5

Acho que essa seria a melhor maneira de fazer isso em Swift:

func filterContentForSearchText(searchText:NSString, scope:NSString)
{
   searchResults = recipes.filter { name.rangeOfString(searchText) != nil  }
}
Harris
fonte
1
Isso é mais idiomático se você estiver filtrando um Sequence, mas há casos em que você precisará de um NSPredicate, como ao lidar com NSFetchedResultsController.
Jarsen
1

Em Swift 2.2

func filterContentForSearchText(searchText: String, scope: String) {
    var resultPredicate = NSPredicate(format: "name contains[c]         %@", searchText)
    searchResults = (recipes as NSArray).filteredArrayUsingPredicate(resultPredicate)
}

Em Swift 3.0

func filterContent(forSearchText searchText: String, scope: String) {
        var resultPredicate = NSPredicate(format: "name contains[c]         %@", searchText)
        searchResults = recipes.filtered(using: resultPredicate)
    }
Saranjith
fonte
1

// mude "nome" e "valor" de acordo com os dados do seu array.

// Altere o nome de "yourDataArrayName" em sua matriz (NSArray).

    let resultPredicate = NSPredicate(format: "SELF.name contains[c] %@", "value")

    if let sortedDta = yourDataArrayName.filtered(using: resultPredicate) as? NSArray {

 //enter code here.

        print(sortedDta)
    }
Hitesh Chauhan
fonte