2012-04-13 12 views
13

¿Cómo usar múltiples condiciones con NSPredicate?Múltiples condiciones en NSPredicate

Estoy usando esto pero no obtengo nada en la matriz devuelta.

NSPredicate *placePredicate = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@ AND category CONTAINS[cd] %@ AND ((dates >= %@) AND (dates <= %@)) AND ((amount >= %f) AND (amount <= %f))",placeTextField.text,selectedCategory,selectedFromDate,selectedToDate,[amountFromTextField.text floatValue],[amountToTextField.text floatValue]]; 

NSArray *placePredicateArray = [dataArray filteredArrayUsingPredicate:placePredicate]; 

NSLog(@"placePredicateArray %@", placePredicateArray); 

La cantidad y la categoría pueden estar vacías a veces. ¿Cómo debería construir el NSPredicate?

Respuesta

13

Me gustaría manejar esta pieza. Es decir,

placePredicate = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@",placeTextField.text]; 
NSMutableArray *compoundPredicateArray = [ NSMutableArray arrayWithObject: placePredicate ]; 

if(selectedCategory != nil) // or however you need to test for an empty category 
    { 
    categoryPredicate = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@",selectedCategory]; 
    [ compoundPredicateArray addObject: categoryPredicate ]; 
    } 

// and similarly for the other elements. 

Tenga en cuenta que no me molesta incluso poniendo en la matriz del predicado para la categoría (o cualquier otra cosa) cuando sé que no es uno.

// Then 
    NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates: 
            compoundPredicateArray ]; 

y si tuviera la intención de hacerlo mucho, yo no utilizar el método de formato, pero mantener alrededor de los bloques de construcción y sólo cambiar cualesquiera que sean los cambios entre usos.

+0

+1 para este comentario '// o como sea que necesite probar una categoría vacía' realmente me ayudó ... ¡gracias! :) – 0yeoj

29

Usted puede construir su placesPredicate utilizando otros NSPredicate objetos y la clase NSCompoundPredicate

Algo así como:

NSPredicate *p1 = [NSPredicate predicateWithFormat:@"place CONTAINS[cd] %@", placeTextField.text]; 
NSPredicate *p2 = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@", selectedCategory]; 
NSPredicate *p3 = [NSPredicate predicateWithFormat:@"(dates >= %@) AND (dates <= %@)", selectedFromDate,selectedToDate]; 
NSPredicate *p4 = [NSPredicate predicateWithFormat:@"(amount >= %f) AND (amount <= %f)", [amountFromTextField.text floatValue],[amountToTextField.text floatValue]]; 

NSPredicate *placesPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[p1, p2, p3, p4]]; 

Ahora, si le falta la categoría, por ejemplo, sólo puede utilizar un maniquí YES predicado para reemplazar it:

NSPredicate *p2; 
if (selectedCategory) { 
    p2 = [NSPredicate predicateWithFormat:@"category CONTAINS[cd] %@", selectedCategory]; 
} else { 
    p2 = [NSPredicate predicateWithBool:YES] 
} 
+0

Gracias. Me ayudó mucho. Gracias –

+0

Pero, ¿cómo obtener una matriz de NSPredicate? –

+0

Si necesita obtener la matriz de predicados utilizada para crear el compuesto, use la propiedad 'subpredicados' de' NSCompoundPredicate'. también debes echarle un buen vistazo a la respuesta de @ DRVic, él crea la matriz de predicados dinámicamente a medida que avanza; esto es un poco más eficiente porque no necesita incluir ningún predicado 'SÍ' pero significa que no lo haces Saber qué predicado está en qué índice en la matriz de subpredicados fácilmente. – deanWombourne

0
Suppose a class Person with attributes "name", "age", "income" 

"personArray" is array of class Person 

NSPredicate *mypredicate = [NSPredicate predicateWithBlock:^BOOL(personObj Person, NSDictionary *bindings) { 
    NSNumber *age = personObj.age; 
    String *name = personObj.name; 
    NSNumber *income = personObj.income 
    BOOL result = (age > 20 && name == "Stack" && income >40000); 
    return result; 
}]; 

NSArray *filteredArray = [personArray filteredArrayUsingPredicate: mypredicate]; 

Para más puede leer este artículo Array Filter Using Blocks

En Swift

let filterArray = personArray.filter 
      { person in 
      let age = personObj.age; 
      let name = personObj.name; 
      let income = personObj.income 
      BOOL result = (age > 20 && name == "Stack" && income >40000); 
      return result; 
     } 
Cuestiones relacionadas