Usando predicados compuesto con SwiftData

Cuando realizamos consultas a la base de datos, utilizamos condiciones con el macro #Predicate.

La versión más simple de un predicado consiste en aplicar una sola condición. Por ejemplo:

let predicate = #Predicate<Product> {
$0.name.localizedStandardContains(criteria)
}

Con este código, creamos un predicado que filtra utilizando criteria y retorna todos los objetos de tipo Product donde la propiedad name contenga el contenido de criteria.

Si quieres una introducción a Swift Data, te recomendamos este artículo.

Predicados compuestos

Si necesitamos crear predicados compuestos, podemos hacer algo como lo siguiente:

let predicate = #Predicate<Trip> {
$0.name.localizedStandardContains(criteria) ||
$0.info.localizedStandardContains(criteria)
}

En este caso, filtramos utilizando la misma condición aplicada a dos propiedades: name o info. El predicado retornará resultados si cualquiera de las dos cumple la condición.

Filtrado con condiciones más complejas

En ocasiones, es necesario aplicar condiciones más elaboradas. Supongamos que estamos desarrollando una aplicación de inventario y queremos realizar una consulta que retorne un listado de productos cuyo nombre contenga los caracteres especificados en la variable criteria, pero que además exista al menos un almacén habilitado relacionado con el producto.

Para este caso, consideremos el siguiente esquema de datos:

La base de datos contiene productos (Product) que pueden estar almacenados en múltiples almacenes (Storage), estableciendo una relación de uno a muchos entre productos y almacenes.

Definimos los modelos así:

@Model
class Storage {
var location: String
var isEnabled: Bool
}
@Model
class Product {
var name: String
var storages: [Storage]
}

El predicado que necesitamos construir se verá así:

// 1
let storagesExpression = #Expression<[Storage], Int> { items in
items.filter {
!$0.isEnabled
}.count
}
// 2
let products = #Predicate<Product>{ product
$0.name.localizedStandardContains(criteria) &&
storagesExpression.evaluate(product.storages) > 0
}

En este código:

  1. Usamos #Expression para definir una expresión que toma como entrada un arreglo de objetos Storage. Filtramos los almacenes donde isEnabled sea true y retornamos el conteo de estos.
  2. Creamos un predicado con dos condiciones:
    1. La propiedad name debe contener los caracteres especificados en criteria.
    2. Utilizamos la expresión storagesExpression para evaluar los almacenes relacionados con el producto, asegurando que el resultado del conteo sea mayor a cero.

Conclusión

Gracias a los predicados, podemos realizar consultas a las bases de datos de manera eficiente. Si combinamos esto con el uso de #Expression, es posible crear consultas más complejas y adaptadas a escenarios específicos.

Comparte este artículo

Subscríbete a nuestro Newsletter

Mantente al día en el mundo de las aplicaciones móviles con nuestro blog especializado.

Artículos semanales

Todas las semanas artículos nuevos sobre el mundo de las aplicaciones móviles.

No spam

No te enviaremos spam, solo contenido de calidad. Puedes darte de baja cuando quieras.

Contenido de calidad

Nada de contenido generado de manera automática usando ChatGPT.

Recomendaciones

Tips indispensables sobre mejores prácticas y metodologías.

© 2025 AsyncLearn