CONCURRENCY¶
Cosa imparerò:
- async-await
- MainActor
- DispatchQueue
Il concurrency in Swift si riferisce alla capacità di eseguire più compiti contemporaneamente, migliorando l'efficienza e la reattività delle applicazioni. In Swift, ci sono diverse tecniche per gestire la concurrency, come i thread, le dispatch e i task asincroni, che consentono di eseguire operazioni in background senza bloccare l'interfaccia utente.
// Funzione asincrona per eseguire la chiamata di rete
func fetchData() async throws -> Data {
// URL della richiesta
let url = URL(string: "https://jsonplaceholder.typicode.com/posts/1")!
// Esecuzione della richiesta di rete e attesa della risposta
let (data, _) = try await URLSession.shared.data(from: url)
// Restituzione dei dati ricevuti
return data
}
// Esecuzione della funzione asincrona
Task {
do {
let data = try await fetchData()
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
print("Risposta del server:", json)
}
} catch {
print("Errore durante la chiamata di rete:", error)
}
}
Output
Risposta del server: ["title": sunt aut facere repellat provident occaecati excepturi optio reprehenderit, "body": quia et suscipit
suscipit recusandae consequuntur expedita et cum
reprehenderit molestiae ut ut quas totam
nostrum rerum est autem sunt rem eveniet architecto, "id": 1, "userId": 1]
@MainActor è un attributo introdotto in Swift 5.5 per segnalare che una classe o una struttura è isolata al main actor, normalmente usato per aggiornare lo stato collegato alla UI. Questo attributo viene utilizzato principalmente in combinazione con async/await per garantire che le operazioni che modificano lo stato dell'interfaccia utente vengano eseguite in modo sicuro e sincronizzato sul thread principale.
@MainActor
struct MainApp {
static func main() async {
// Eseguiamo il nostro codice principale all'interno di una funzione asincrona
try? await Task.sleep(nanoseconds: 1 * 1_000_000_000) // Simuliamo un'attesa di 1 secondo
print("Codice principale eseguito sul main actor")
}
}
In questo esempio, MainApp è un main actor, contrassegnato dall'attributo @MainActor. La funzione main() è una funzione asincrona, che viene eseguita sul main actor. Utilizziamo await per eseguire l'attesa all'interno della funzione asincrona. Essendo contrassegnata come @MainActor, questa funzione può interagire con l'interfaccia utente in modo sincronizzato e sicuro.
Grand Central Dispatch (GCD) è una libreria che permette di gestire l’esecuzione concorrente del codice tramite code. In genere si usa una coda in background per svolgere operazioni pesanti, come il caricamento o l’elaborazione di dati, e poi si torna sulla main queue per aggiornare l’interfaccia utente.
// Simuliamo un'operazione che richiede tempo
DispatchQueue.global(qos: .userInitiated).async {
let risultato = "Dati caricati"
DispatchQueue.main.async {
print(risultato)
}
}