Si vous faites partie de mes lecteurs réguliers, vous devez très certainement bercer dans le milieu du développement iOS, et plus particulière en Swift.

Bien que les bases du Swift soient faciles à apprendre et à maitriser, le fait d’utiliser le langage au quotidien permet d’apprendre et de découvrir des fonctionnalités moins connues. Aujourd’hui, je vais vous montrer quelques astuces que j’ai découvert avec le temps. J’espère que celles-ci vous seront utiles et qu’elles permettront d’améliorer la qualité de votre code et sa lisibilité.

Commençons sans plus tarder !

Des extensions pour vos constantes

Comme vous le savez certainement, je me passe des storyboards dans mon développement et j’écris toutes mes interfaces utilisateurs directement avec du code grâce à la librairie Snapkit pour gérer mes contraintes (voir Démarrer un projet Xcode sans storyboard et Des librairies pour des meilleures contraintes).

Et il arrive très souvent que nous ayons recours à des nombres constants lors de l’écriture de contraintes, par exemple, pour créer des marges:

private func setupConstraints() {
    titleLabel.snp.makeConstraints {
        $0.leading.equalToSuperview().offset(20)    // Applique une marge de 20 sur le côté gauche
        $0.trailing.equalToSuperview().offset(-20)   // Applique une marge de 20 sur le côté droit
    }
}

Le problème avec ceci, c’est que ce n’est pas facilement maintenable. En effet, si un jour je veux réduire ces marges, je devrais chercher partout où j’ai spécifiée de marges de 20et les modifier une à une.

C’est pourquoi je vous propose la solution suivante: nous allons créer une extension de notre view controller, dans lequel nous allons créer une énumération nommée Layout, et c’est dans celle-ci que nous écrirons nos constantes, ainsi, elles seront toutes situées au même endroit et seront beaucoup plus faciles à modifier.

extension MyViewController {
    enum Layout {
        enum TitleLabel {
            static let horizontalOffset: CGFloat = 20
        }
    }
}

Ce qui nous permet de transformer le code précédent en ceci:

private func setupConstraints() {
    titleLabel.snp.makeConstraints {
        $0.leading.equalToSuperview().offset(Layout.TitleLabel.horizontalOffset)
        $0.trailing.equalToSuperview().offset(-Layout.TitleLabel.horizontalOffset)
    }
}

Et voilà, notre code est devenu beaucoup plus facile à maintenir, et beaucoup plus facile à lire !

Bien entendu, je vous ai montré cette astuce avec des constantes en rapport avec de l’UI, mais elle est aussi applicable dans le cas d’autres constantes, comme par exemple, un nombre de secondes à attendre afin de définir un timer statique.

Améliorer la lisibilité des constantes globales

Premièrement, si vous n’utilisez pas de constantes globales, je vous encourage à le faire, deuxièmement, si vous en utilisez, il est fort probables qu’elles ressemblent à ceci:

struct Constants {
    static let myBaseUrl = "https://sonnyfournier.github.io/"
    static let myBlogEndpoint = "blog/"

    static let twitterApiBaseUrl = "https://api.twitter.com/1.1/"
    static let twitterTimelineEndpoint = "timeline/"
}

Ce que je vous propose aujourd’hui, c’est de tirer avantage des nested structures, autrement dit, des structures dans d’autres structures, afin d’améliorer l’utilisation et la lisibilité de ces constantes.

struct Constants {
    struct MySiteApi {
        static let baseUrl = "https://sonnyfournier.github.io/"
        static let blogEndpoint = "blog/"
    }

    struct TwitterApi {
        static let baseUrl = "https://api.twitter.com/1.1/"
        static let timelineEndpoint = "timeline/"
    }
}

De cette manière, toutes vos constantes seront proprement isolées les unes des autres et seront d’autant plus faciles à utiliser:

let url = Constants.TwitterApi.baseUrl

En lisant ce code on sait immédiatement à quoi on accède et on évite les noms de variables à rallonge.

Defer

Bien qu’introduit avec Swift 2.0, l’instruction defer semble méconnue par beaucoup de développeurs iOS.

Cette instruction permet un moyen sûr et simple d’exécuter du code juste avant de quitter le scope d’une fonction.

func myFunc() {
    defer {
        print("Defer here")
    }

    print("End of function")
}

// Affichera:
// "End of function"
// "Defer here"

Defer peut se montrer très utile dans les cas où un nettoyage est nécéssaire avant de quitter une fonction par exemple.

Conserver les initialisateurs par défaut

Swift est un langage intelligent et automatise beaucoup de choses pour nous. Par exemple, si je définis une structure Vehicule de la sorte:

struct Vehicule {
    let wheelsCount: Int
    let seatsCount: Int
}

Swift va alors créer un initialisateur automatiquement pour cette structure (init(wheelsCount:seatsCount:)) que nous pourrons utiliser de la manière suivante:

let car = Vehicule(wheelsCount: 4, seatsCount: 5)

Malheureusement, cet initialisateur par défaut ne sera plus disponible si nous définissons un initialisateur custom:

struct Vehicule {
    let wheelsCount: Int
    let seatsCount: Int

    init(dictionary: [String: Int]) {
        self.wheelsCount = dictionary["wheelsCount"] ?? 4
        self.seatsCount = dictionary["seatsCount"] ?? 5
    }
}

L’initialisateur init(wheelsCount:seatsCount:) ne sera plus disponible et nous devrons utiliser celui que nous venons de définir. Or parfois, il est utile de conserver celui par défaut. Heureusement pour nous, il existe une solution très simple pour cela: il suffit de créer une extension de notre structure dans laquelle nous allons définir notre initialisateur custom:

struct Vehicule {
    let wheelsCount: Int
    let seatsCount: Int
}

extension Vehicule {
    init(dictionary: [String: Int]) {
        self.wheelsCount = dictionary["wheelsCount"] ?? 4
        self.seatsCount = dictionary["seatsCount"] ?? 5
    }
}

Grâce à cette manipulation, nous pourrons désormais utiliser les deux initialisateurs, celui par défaut, et le nôtre !

Conclusion

Nous avons fait le tour aujourd’hui des astuces que j’avais à vous proposer, j’espère sincèrement que celles-ci vous auront étés utiles si vous ne les connaissiez pas.

Comme à mon habitude je vous invite à me partager vos astuces si vous en avez, je me ferais une joie de les partager dans un futur article !