Optimisation des performances des applications Swift pour débutants

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi les performances comptent dès le premier jour



Lorsque vous commencez à écrire en Swift, il est facile de se concentrer uniquement sur la fonctionnalité : « tant que ça marche ». Cependant, les développeurs expérimentés le savent : l'optimisation des performances n'est pas une touche finale, mais un socle qui se pose dès les premières lignes de code. Une application lente perd des utilisateurs, épuise la batterie et reçoit de mauvais avis.



Dans cet article, nous allons décomposer les aspects clés de l'optimisation des applications Swift pour iOS et macOS. Vous apprendrez à éviter les erreurs typiques des débutants, à travailler avec la mémoire, les threads et le profilage. Chaque section contient des exemples de code pratiques que vous pouvez immédiatement appliquer dans vos projets.



1. Gestion de la mémoire : ARC et prévention des cycles de rétention



Swift utilise le Comptage Automatique de Références (ARC) pour la gestion de la mémoire. Cela signifie que les objets sont libérés lorsqu'il n'y a plus de références fortes vers eux. Mais si vous créez une référence cyclique (cycle de rétention), la mémoire ne sera jamais libérée — une fuite se produira.



Références faibles (weak) et non possédées (unowned)

Utilisez weak et unowned pour briser les cycles. Cela est le plus souvent nécessaire dans les closures et les délégués.



class ViewController: UIViewController {    var networkManager: NetworkManager?        func fetchData() {        networkManager?.fetch { [weak self] result in            guard let self = self else { return }            // Handle the result            self.updateUI(with: result)        }    }}


Quand les utiliser :

  • weak — si la référence peut devenir nil (ex : délégué).
  • unowned — si vous êtes sûr que l'objet survivra à la closure (ex : contrôleur parent).


Éviter les copies inutiles

Les types valeur (structures, énumérations) sont copiés lors de l'affectation. Pour les grandes données, utilisez class ou passez par référence en utilisant inout.



// Mauvais : copier un grand tableaufunc processLargeArray(_ array: [Int]) {    // array — une copie}

// Bon : passage par référencefunc processLargeArray(_ array: inout [Int]) { // array — une référence à l'original}


2. Travail avec le multithreading : GCD et async/await



iOS et macOS sont des systèmes multithreadés. Si vous effectuez des opérations lourdes (chargement de données, traitement d'images) sur le thread principal, l'interface « se fige ». Utilisez Grand Central Dispatch (GCD) ou le moderne async/await.



GCD : motifs de base

DispatchQueue.global(qos: .userInitiated).async {    // Travail lourd en arrière-plan    let result = performHeavyCalculation()        DispatchQueue.main.async {        // Mise à jour de l'interface sur le thread principal        self.label.text = "\\(result)"    }}


QoS (Quality of Service) :

  • .userInteractive — pour l'interface utilisateur (quasi instantané).
  • .userInitiated — pour les actions de l'utilisateur (quelques secondes).
  • .utility — pour les tâches de longue durée (barres de progression).
  • .background — pour la synchronisation en arrière-plan (pas urgent).


Async/await (Swift 5.5+)

Une manière plus lisible de travailler avec l'asynchrone :

func fetchImage(from url: URL) async throws -> UIImage {    let (data, _) = try await URLSession.shared.data(from: url)    guard let image = UIImage(data: data) else {        throw URLError(.badServerResponse)    }    return image}

// Appel dans une TaskTask { do { let image = try await fetchImage(from: url) self.imageView.image = image } catch { print("Erreur de téléchargement : \\(er")

Blogs

Book Recommendations