[SC] Ejecutando Tasks en SwiftUI
Source: Dev.to
¿Qué relación tiene el ejemplo de búsqueda con .task?
Se retoma el ejemplo de search(_ query: String) donde se filtran unas entradas pasado un rebote de 500 ms. En este ejemplo, se necesita guardar una referencia de un Task para luego cancelarlo, en la clase ArticleSearcher (que es Observable). Más tarde, desde la vista se invoca el método search(_:) desde un onChange(of:).
@MainActor
@Observable
final class ArticleSearcher {
private static let articleTitlesDatabase = [
"Article one",
"Article two",
"Article three",
]
var searchResults: [String] = ArticleSearcher.articleTitlesDatabase
private var currentSearchTask: Task?
func search(_ query: String) {
currentSearchTask?.cancel()
currentSearchTask = Task {
do {
try await Task.sleep(for: .milliseconds(500))
print("Starting to search!")
searchResults = Self.articleTitlesDatabase.filter {
$0.lowercased().contains(query.lowercased())
}
} catch {
print("Search was cancelled!")
}
}
}
}¿Cómo funciona el modificador .task?
SwiftUI permite enganchar un Task al ciclo de vida de una vista por medio de .task(). La tarea se programa antes de que aparezca la vista y se cancela cuando desaparece. Ya no es necesario envolver la tarea a disparar con Task { }, sino que basta con hacer async la firma del método.
Estado final de search(_ query: String)
func search(_ query: String) async {
do {
try await Task.sleep(for: .milliseconds(500))
print("Starting to search!")
searchResults = Self.articleTitlesDatabase
.filter { $0.lowercased().contains(query.lowercased()) }
} catch {
print("Search was cancelled!")
}
}¿Para qué sirve el parámetro id: en .task?
.task() dispara una tarea antes de que aparezca una vista. Cuando el valor del parámetro id: cambia, se cancela la tarea anterior de forma automática y se vuelve a disparar una nueva.
¿Para qué sirve el parámetro .priority en .task?
Como Swift Concurrency tiene un pool de hilos cooperativo, podemos cambiar la prioridad para obtener un comportamiento diferente con respecto a otras tareas. SwiftUI usa por defecto userInitiated, así que, en principio, tiene sentido cambiar la prioridad a media (utility) o baja (background).