Utilizzo di Predicate in Swift


93

Sto lavorando al tutorial qui (imparando Swift) per la mia prima app: http://www.appcoda.com/search-bar-tutorial-ios7/

Sono bloccato su questa parte (codice Objective-C):

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

Qualcuno può consigliare come creare un equivalente per NSPredicate in Swift?

Risposte:


158

Questo è davvero solo un cambio di sintassi. OK, quindi abbiamo questa chiamata al metodo:

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

In Swift, i costruttori saltano la parte "blahWith ..." e usano semplicemente il nome della classe come funzione e poi vanno direttamente agli argomenti, così [NSPredicate predicateWithFormat: …]diventerebbe NSPredicate(format: …). (Per un altro esempio, [NSArray arrayWithObject: …]diventerebbe NSArray(object: …). Questo è un modello regolare in Swift.)

Quindi ora dobbiamo solo passare gli argomenti al costruttore. In Objective-C, i letterali NSString hanno l'aspetto @"", ma in Swift usiamo solo le virgolette per le stringhe. Quindi questo ci dà:

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

E in effetti è esattamente ciò di cui abbiamo bisogno qui.

(Per inciso, noterai che alcune delle altre risposte usano invece una stringa di formato come "name contains[c] \(searchText)". Non è corretto. Utilizza l'interpolazione di stringhe, che è diversa dalla formattazione del predicato e generalmente non funzionerà per questo.)


Grazie. Mi salvi un giorno!
Hugo

2
Per affrontare la seconda riga del tuo metodo, potresti usare il predicato come:searchResults = recipes.filter { resultPredicate.evaluateWithObject($0) }
Ben Packard

43

Lavorare con il predicato per un periodo piuttosto lungo. Ecco la mia conclusione (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
Con cosa è uguale LIKE 'a%z'?
TomSawyer

@ Jiří Zahálka Che cosa significa richiesta di sentire?
Muju

28

Esempio di come utilizzare in 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) }

Otterrai (parco giochi)

inserisci qui la descrizione dell'immagine


E se ... Se ho una serie di dizionari? Come si analizzano per ottenere i dati?
Revathy Durairajan

1
@RevathyDurairajan hai bisogno di SELF.yourkeyname per filtrare l'array di dizionari.
Pawan Rai

11

Puoi utilizzare i filtri disponibili in swift per filtrare il contenuto da un array invece di utilizzare un predicato come in Objective-C.

Un esempio in Swift 4.0 è il seguente:

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

Nell'esempio precedente, poiché ogni elemento dell'array è una stringa, è possibile utilizzare il containsmetodo per filtrare l'array.

Se l'array contiene oggetti personalizzati, le proprietà di quell'oggetto possono essere utilizzate per filtrare gli elementi in modo simile.


6

Usa il codice seguente:

 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
Per qualche motivo scriverlo in quel modo non ha funzionato per me, tuttavia lasciare che myPredicateString = "name contiene [c] (searchText)" e poi eseguire var resultPredicate: NSPredicate = NSPredicate (format: myPredicateString) lo ha fatto
AppHandwerker

5

Penso che questo sarebbe un modo migliore per farlo in Swift:

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

1
Questo è più idiomatico se stai filtrando a Sequence, ma ci sono casi in cui avrai bisogno di a NSPredicate, come quando hai a che fare con NSFetchedResultsController.
Jarsen

1

In swift 2.2

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

In swift 3.0

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

1

// cambia "nome" e "valore" in base ai dati dell'array.

// Cambia il nome "yourDataArrayName" in base all'array (NSArray).

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

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

 //enter code here.

        print(sortedDta)
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.