Utilisation de Predicate dans Swift


93

Je travaille sur le tutoriel ici (apprentissage de Swift) pour ma première application: http://www.appcoda.com/search-bar-tutorial-ios7/

Je suis coincé sur cette partie (code Objective-C):

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

Quelqu'un peut-il conseiller comment créer un équivalent pour NSPredicate dans Swift?

Réponses:


158

C'est vraiment juste un commutateur de syntaxe. OK, nous avons donc cet appel de méthode:

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

Dans Swift, les constructeurs ignorent la partie "blahWith…" et utilisent simplement le nom de la classe comme fonction, puis vont directement aux arguments, ce [NSPredicate predicateWithFormat: …]qui deviendrait NSPredicate(format: …). (Pour un autre exemple, [NSArray arrayWithObject: …]deviendraitNSArray(object: …) . Il s'agit d'un modèle régulier dans Swift.)

Alors maintenant, nous avons juste besoin de passer les arguments au constructeur. En Objective-C, les littéraux NSString ressemblent à @"", mais dans Swift, nous utilisons simplement des guillemets pour les chaînes. Cela nous donne donc:

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

Et en fait, c'est exactement ce dont nous avons besoin ici.

(Incidemment, vous remarquerez que certaines des autres réponses utilisent à la place une chaîne de format comme "name contains[c] \(searchText)". Ce n'est pas correct. Cela utilise une interpolation de chaîne, qui est différente du formatage des prédicats et ne fonctionnera généralement pas pour cela.)


Merci. Vous me sauvez un jour!
Hugo

2
Pour adresser la deuxième ligne de votre méthode, vous pouvez utiliser le prédicat comme:searchResults = recipes.filter { resultPredicate.evaluateWithObject($0) }
Ben Packard

43

Travailler avec un prédicat depuis assez longtemps. Voici ma conclusion (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])

1
Qu'est-ce qui est égal LIKE 'a%z'?
TomSawyer

@ Jiří Zahálka Que signifie la demande d'entendre?
Muju

28

Exemple d'utilisation dans 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) }

Vous obtiendrez (terrain de jeu)

entrez la description de l'image ici


Et si ... si j'ai un éventail de dictionnaires? Comment analyser pour obtenir les données?
Revathy Durairajan

1
@RevathyDurairajan vous avez besoin de SELF.yourkeyname pour filtrer le tableau de dictionnaires.
Pawan Rai

11

Vous pouvez utiliser les filtres disponibles dans swift pour filtrer le contenu d'un tableau au lieu d'utiliser un prédicat comme dans Objective-C.

Un exemple dans Swift 4.0 est le suivant:

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

Dans l'exemple ci-dessus, puisque chaque élément du tableau est une chaîne, vous pouvez utiliser le contains méthode pour filtrer le tableau.

Si le tableau contient des objets personnalisés, les propriétés de cet objet peuvent être utilisées pour filtrer les éléments de la même manière.


6

Utilisez le code ci-dessous:

 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)
}

1
Pour une raison quelconque, l'écrire comme ça n'a pas fonctionné pour moi, mais laisser myPredicateString = "name contains [c] (searchText)" puis faire var resultPredicate: NSPredicate = NSPredicate (format: myPredicateString) a fait
AppHandwerker

5

Je pense que ce serait une meilleure façon de le faire dans Swift:

func filterContentForSearchText(searchText:NSString, scope:NSString)
{
   searchResults = recipes.filter { name.rangeOfString(searchText) != nil  }
}

1
C'est plus idiomatique si vous filtrez a Sequence, mais il y a des cas où vous aurez besoin d'un NSPredicate, comme pour traiter NSFetchedResultsController.
Jarsen

1

Dans Swift 2.2

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

Dans Swift 3.0

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

1

// changez "nom" et "valeur" en fonction des données de votre tableau.

// Changez le nom "yourDataArrayName" en fonction de votre tableau (NSArray).

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

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

 //enter code here.

        print(sortedDta)
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.