Usar predicado en Swift


93

Estoy trabajando en el tutorial aquí (aprendiendo Swift) para mi primera aplicación: http://www.appcoda.com/search-bar-tutorial-ios7/

Estoy atascado en esta parte (código Objective-C):

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

¿Alguien puede aconsejar cómo crear un equivalente para NSPredicate en Swift?

Respuestas:


158

En realidad, esto es solo un cambio de sintaxis. OK, entonces tenemos esta llamada al método:

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

En Swift, los constructores omiten la parte "blahWith ..." y simplemente usan el nombre de la clase como una función y luego van directamente a los argumentos, así [NSPredicate predicateWithFormat: …]se convertiría NSPredicate(format: …). (Otro ejemplo, [NSArray arrayWithObject: …]se convertiría en NSArray(object: …). Este es un patrón regular en Swift).

Entonces ahora solo necesitamos pasar los argumentos al constructor. En Objective-C, los literales NSString se ven así @"", pero en Swift solo usamos comillas para las cadenas. Entonces eso nos da:

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

Y de hecho eso es exactamente lo que necesitamos aquí.

(Por cierto, notará que algunas de las otras respuestas usan una cadena de formato como "name contains[c] \(searchText)". Eso no es correcto. Eso usa interpolación de cadenas, que es diferente del formato de predicado y generalmente no funcionará para esto).


Gracias. ¡Me salvas un día!
Hugo

2
Para abordar la segunda línea de su método, puede usar el predicado como:searchResults = recipes.filter { resultPredicate.evaluateWithObject($0) }
Ben Packard

43

Trabajando con predicado durante bastante tiempo. Aquí está mi conclusión (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é es igual a LIKE 'a%z'?
TomSawyer

@ Jiří Zahálka ¿Qué es la petición de escuchar?
Muju

28

Ejemplo de uso en 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) }

Obtendrás (patio de recreo)

ingrese la descripción de la imagen aquí


¿Y si ... si tengo una variedad de diccionarios? ¿Cómo analizo para obtener los datos?
Revathy Durairajan

1
@RevathyDurairajan necesita SELF.yourkeyname para filtrar la matriz de diccionarios.
Pawan Rai

11

Puede usar filtros disponibles en Swift para filtrar el contenido de una matriz en lugar de usar un predicado como en Objective-C.

Un ejemplo en Swift 4.0 es el siguiente:

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

En el ejemplo anterior, dado que cada elemento de la matriz es una cadena, puede usar el containsmétodo para filtrar la matriz.

Si la matriz contiene objetos personalizados, las propiedades de ese objeto se pueden usar para filtrar los elementos de manera similar.


6

Utilice el siguiente código:

 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
Por alguna razón, escribirlo así no funcionó para mí, sin embargo, dejar myPredicateString = "nombre contiene [c] (searchText)" y luego hacer var resultPredicate: NSPredicate = NSPredicate (formato: myPredicateString) sí
AppHandwerker

5

Creo que esta sería una mejor manera de hacerlo en Swift:

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

1
Esto es más idiomático si está filtrando un Sequence, pero hay casos en los que necesitará un NSPredicate, como cuando se trata de NSFetchedResultsController.
Jarsen

1

En Swift 2.2

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

En 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 "nombre" y "valor" de acuerdo con los datos de tu matriz.

// Cambie el nombre de "yourDataArrayName" según su 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)
    }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.