UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Lister des images avec le gestionnaire de fichiers (FileManager)

Les images que je vous ai fournies proviennent de la NOAA (National Oceanic and Atmospheric Administration), une agence gouvernementale américaine qui produit du contenu dans le domaine public et que nous pouvons librement réutiliser. Une fois qu'elles ont été copiées dans votre projet, Xcode les intégrera automatiquement dans votre application finale, lors de la phase de compilation, afin que vous puissiez y accéder.

En coulisse, une application iOS est en réalité un répertoire contenant de nombreux fichiers : le fichier binaire lui-même (c'est la version compilée de votre code prêt à être exécuté), tout le contenu multimédia que votre application utilise, tous les fichiers relatifs à la présentation visuelle, ainsi que d'autres choses variées telles que des métadonnées et les droits liés à la sécurité.

Ce répertoire s'appelle un paquet (Bundle en anglais) et porte l'extension .app. Comme nos fichiers multimédias sont perdus dans l'arborescence du répertoire, nous pouvons demander au système de nous indiquer tous les fichiers présents dans le dossier, puis d'extraire ceux que nous voulons. Vous avez peut-être remarqué que le nom de toutes les images commence par "nssl" (abréviation de National Severe Storms Laboratory). Notre tâche est donc simple : lister tous les fichiers présents dans le répertoire de notre application et extraire ceux commençant par "nssl".

Pour l'instant, nous allons charger cette liste et seulement l’afficher dans le visualiseur de logs intégré à Xcode, mais nous les ferons bientôt apparaître dans notre application.

Donc première étape : ouvrir le fichier ViewController.swift. Un contrôleur de vue (view controller) peut être considéré comme un écran contenant des informations, ce qui pour nous correspond pour le moment à notre écran tout blanc. Le fichier ViewController.swift est responsable de l’affichage de cet écran vide, et pour l'instant, il ne contient pas beaucoup de code. Vous devriez voir quelque chose comme :

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

Ce code contient cinq éléments intéressants dont je veux vous parler avant de continuer.

  1. Le fichier commence par import UIKit, ce qui signifie que "ce fichier fera référence à la boîte à outils relative à l'interface utilisateur d'iOS."
  2. La ligne class ViewController: UIViewController signifie "je veux créer un nouvel écran appelé ViewController contenant des données, et basé sur UIViewController." Lorsqu'un type de données commence par "UI", cela signifie qu'il provient de UIKit. UIViewController est le type d'écran par défaut, vide et blanc, jusqu'à ce que nous le modifions.
  3. La ligne override func viewDidLoad() commence une méthode (un bloc de code), qui est un morceau de code situé dans notre écran ViewController. Le mot-clé override est nécessaire car il signifie que "nous voulons modifier le comportement par défaut du UIViewController fourni par Apple". ViewDidLoad() est appelée lorsque l’écran a été chargé et est prêt à être personnalisé.
  4. Il y a beaucoup de caractères { et }. Ces symboles, appelés accolades, sont utilisés pour délimiter des blocs de code. Il est généralement conseillé de mettre en retrait les lignes de code à l'intérieur des accolades afin d'identifier plus facilement où commence et se termine un bloc de code. Les accolades situées le plus à l'extérieur contiennent l'intégralité du code relatif au type de données ViewController. Les accolades situées à l'intérieur marquent le début et la fin de la méthode viewDidLoad().
  5. La méthode viewDidLoad() contient la ligne de code super.viewDidLoad() et un commentaire (la ligne commençant par //). Le terme super signifie "indique au UIViewController d'Apple d'exécuter son propre code avant que je n'exécute le mien", et vous verrez que ce mot est souvent utilisé.

Nous reviendrons souvent sur ce code dans les prochains projets ; ne vous inquiétez pas si tout est un peu flou pour le moment.

Pas de numéro de lignes ? Lorsque vous lisez du code, il est souvent utile d’afficher le numéro des lignes afin que vous puissiez repérer plus facilement un morceau de code spécifique. Si Xcode ne vous affiche pas le numéros des lignes par défaut, je vous suggère d'activer cette option dès à présent : cliquez sur Xcode dans la barre des menus et choisissez Preferences..., puis cliquez sur l'onglet Text Editing et assurez-vous que "Line numbers" est coché.

Comme je l'ai dit précédemment, la méthode viewDidLoad() est appelée lorsque l'écran a été chargé et est prêt à être personnalisé. Tout ce qui se trouve entre func viewDidLoad() { et } qui suit quelques lignes plus bas fait partie de cette méthode et sera appelé lorsque vous pourrez commencer à personnaliser l'écran.

Nous allons ajouter un peu de code dans cette méthode pour charger les images NSSL. Ajoutez ceci sous la ligne super.viewDidLoad() :

let fm = FileManager.default
let path = Bundle.main.resourcePath!
let items = try! fm.contentsOfDirectory(atPath: path)

for item in items {
    if item.hasPrefix("nssl") {
        // this is a picture to load!
    }
}

Remarque : Certains développeurs expérimentés en Swift, en lisant ce code et en voyant try!, vont très certainement avoir envi de m'envoyer un courrier électronique incendiaire. Si vous envisagez de faire cela, lisez tout d'abord ce qui suit.

C’est un gros morceau de code, qui est complètement nouveau. Passons en revue ce qu’il fait ligne par ligne :

  • La ligne let fm = FileManager.default déclare une constante appelée fm et lui assigne la valeur retournée par FileManager.default. C'est un type de données qui nous permet de travailler avec le système de fichiers, que nous allons utiliser dans notre cas pour rechercher des fichiers.
  • La ligne let path = Bundle.main.resourcePath! déclare une constante appelée path à qui on assigne le chemin du paquet de notre application. Souvenez vous qu'un paquet est un répertoire contenant notre programme compilé et toutes nos ressources. Ainsi, cette ligne signifie : "dis-moi où je peux trouver toutes les images que j'ai ajoutées à mon application".
  • La ligne let items = try! fm.contentsOfDirectory(atPath: path) déclare une troisième constante appelée items et lui assigne le contenu du répertoire situé dans path. Path correspond au chemin du paquet de notre application, qui a été retourné par la ligne précédente. Comme vous pouvez le constater, les noms des méthodes fournies par Apple sont relativement longs, rendant le code plus lisible ! La constante items est un tableau (array) - une collection - contenant les noms de tous les fichiers trouvés dans le répertoire contenant les ressources de notre application.
  • La ligne for item in items { commence une boucle. Une boucle est un bloc de code qui s'exécute plusieurs fois. Dans le cas présent, la boucle s'exécute pour chaque élément trouvé dans le paquet de l'application. Notez que la ligne se termine par une accolade ouvrante, indiquant le début d'un nouveau bloc de code, et qu'il y a l'accolade fermante correspondante quatre lignes plus bas. Tout ce qui se trouve à l'intérieur de ces accolades sera exécuté à chaque itération de la boucle. Nous pourrions traduire cette ligne par "traite items comme une collection de chaînes de caractères, puis extrais chacune de ces chaînes et attribue-la à item, puis exécute le code qui suit…"
  • La ligne if item.hasPrefix("nssl") { est la première ligne de notre boucle. À ce stade, nous sommes prêts à travailler avec le nom du premier fichier qui a été assigné à item. Pour déterminer s'il s'agit d'un nom qui nous intéresse, nous utilisons la méthode hasPrefix() : elle prend un paramètre (le préfixe à rechercher) et retourne true ou false. Le "if" du début indique que cette ligne est une instruction conditionnelle : si l'élément a le préfixe "nssl", alors ... c'est vrai, et une autre accolade ouvrante marque un nouveau bloc de code. Cette fois, le code ne sera exécuté que si hasPrefix() a retourné la valeur true.
  • Enfin, la ligne // this is a picture to load! (ceci est une image à charger!) est un commentaire - si nous arrivons jusqu'ici, item contient le nom d'une image à charger depuis notre paquet, nous devons donc le stocker quelque part.

Ces quelques lignes de code contiennent beaucoup de notions importantes, donc avant de continuer, récapitulons :

  • Nous utilisons let pour déclarer des constantes. Les constantes correspondent à des données que nous souhaitons référencer, tout en sachant que leur valeur ne sera pas modifiée. Par exemple, votre date de naissance est une constante, mais votre âge ne l’est pas - votre âge est une variable, car il change tous les ans.
  • Les programmeurs en Swift aiment plutôt utiliser des constantes là où la plupart des développeurs utilisent des variables. En effet, en programmant, vous allez vous rendre compte que la plupart des données que vous stockez ne changent pas beaucoup, donc vous pouvez les déclarer comme des constantes. Cela permet au système de faire fonctionner votre code plus rapidement et de le sécuriser car si vous essayez de modifier une constante, Xcode refusera de compiler votre application.
  • En Swift, du texte est représenté par le type de données String (Chaîne de caractères). Les chaînes de caractères en Swift sont extrêmement puissantes et fonctionnent avec toutes les langues auxquelles vous pouvez penser - Anglais, Chinois, Klingon et plus.
  • Les collections de données s'appellent des tableaux (Arrays) et ne peuvent généralement contenir qu'un seul type de données à la fois. Un tableau de chaînes de caratères est écrit sous la forme [String] et ne peut contenir que des chaînes de caractères. Si vous essayez de mettre des nombres, Xcode refusera de compiler votre application.
  • Le mot-clé try! signifie "le code suivant risque de ne pas fonctionner correctement, mais je suis absolument certain que ce ne sera pas le cas". Si le code échoue, par exemple si le répertoire que nous avons demandé n'existe pas - notre application va planter.
  • Dans notre cas, nous pouvons tout à fait utiliser "try!", car si ce code échoue, cela signifie que notre application n'arrive pas à lire ses propres données et ça veut dire qu'il y a un sérieux problème ! Certains développeurs en Swift essayent d'écrire du code pour gérer ce type d'erreurs qui font crasher l'application au moment de son exécution, mais malheureusement, ils ne font que masquer trop souvent le problème rencontré.
  • Vous pouvez utiliser for someItem in someArray pour parcourir tous les éléments d'un tableau. Swift extrait chaque élément et exécute le code dans la boucle une fois pour chaque élément.

Si vous êtes très attentif, vous avez peut-être remarqué une toute petite chose mais qui est également l'une des parties les plus compliquées de Swift. Je vais donc la garder aussi simple que possible pour le moment, puis je la développerais davantage plus tard : c'est le point d'exclamation à la fin de Bundle.main.resourcePath!

Non, ce n'était pas une faute de frappe de ma part. Si vous supprimez le point d'exclamation, le code ne fonctionnera plus. Xcode pense donc que c'est important - et c'est effectivement le cas. Swift a trois façons de travailler avec les données :

  1. Une variable ou une constante contenant des données. Par exemple, name: String est une chaîne de caractères appelée name.
  2. Une variable ou une constante pouvant contenir des données, mais nous n'en sommes pas certains. Cela s'appelle un type optionnel, et ressemble à ceci: name: String? Vous ne pouvez pas l'utiliser directement, vous devez d'abord demander à Swift de vérifier si elle a une valeur.
  3. Une variable ou une constante pouvant contenir des données ou non, mais nous sommes certains à 100% qu'elle en contient - du moins une fois qu’elle a été définie. Cela s'appelle un type optionnel implicitement déballé, et se présente comme suit : name: String! Vous pouvez l'utiliser directement.

Lorsque j’explique cela aux gens, ils sont presque toujours désorientés. Ne vous inquiétez donc pas si ce qui précède n’a aucun sens pour vous. Nous reviendrons sans cesse sur les types optionnels dans les projets à venir, alors laissez-vous du temps.

Nous étudierons les types optionnels plus en détail ultérieurement, mais pour l’instant, l’important c'est que Bundle.main.resourcePath peut nous retourner ou non une chaîne de caractères, et renvoie donc le type de donnéesString? - c’est-à-dire une chaîne de caractères optionnelle. En ajoutant le point d'exclamation à la fin, nous forçons le débalage de cet optionnel, ce qui signifie que nous disons : "je suis sûr que cette chaîne de caractères retournera une vraie chaîne de caractères, et ne sera jamais nil (sans valeur), donc merci de me la donner comme une chaîne de caractères normale".

Avertissement important : si vous essayez d'utiliser une constante ou une variable ayant une valeur nil, votre application va planter. C'est pour cela que certaines personnes ont nommé le ! l'opérateur de "crash ", car il est facile de se tromper. Et c'est exactement la même chose pour "try!". Ne vous inquiétez pas si tout cela vous semble dur pour le moment, à force de l'utiliserer ça deviendra naturel.

Pour le moment, notre code charge la liste des fichiers contenus dans le paquet de notre application, puis les parcourt un par un pour trouver ceux dont le nom commence par «nssl». Cependant, il ne fait rien avec ces fichiers. Nous allons donc créer un tableau (Array) avec toutes les images "nssl" afin de pouvoir les retrouver plus tard, sans avoir à parcourir à chaque fois le répertoire contenant les ressources.

Les trois constantes que nous avons déjà créées - fm, path et items - existent au sein de la méthode viewDidLoad() et seront détruites à la fin de l'exécution de cette méthode. Ce que nous voulons, c'est un moyen d'assigner ces données au type ViewController, de manière à ce qu'elles existent aussi longtemps que notre écran. En Swift, cela se fait en utilisant une "propriété" : nous pouvons donner autant de propriétés que nous voulons au type ViewController, puis les lire et les modifier aussi souvent que nécessaire tant que l'écran existe.

Pour créer une propriété, vous devez la déclarer à l'extérieur des méthodes. Nous avons créé des constantes en utilisant let jusqu'à présent, mais comme ce tableau va être modifié dans notre boucle, nous devons donc le rendre variable. Nous devons également indiquer à Swift le type de données exact que la variable va contenir. Dans notre cas, il s’agit d’un tableau (Array) de chaînes de caractères, où chaque élément correspond au nom d’une image «nssl».

Ajoutez cette ligne de code avant viewDidLoad():

var pictures = [String]()

Si vous l'avez placé au bon endroit, votre code devrait ressembler à ceci:

class ViewController: UIViewController {
    var pictures = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let fm = FileManager.default

Le mot-clé var est utilisé pour créer des variables, de la même manière que let l'est pour créer des constantes. Les choses deviennent un peu bizarre dans la deuxième partie de la seconde ligne : [String](). C'est en fait deux choses en une : [String] signifie "un tableau de chaînes de caractères", et () signifie "en créer un maintenant". Les parenthèses ici sont comme celles que l'on trouve dans la méthode viewDidLoad() - elles signalent le nom d'un autre code à exécuter, dans ce cas le code permettant de créer un nouveau tableau de chaînes de caratères.

Ce tableau pictures sera créé en même temps que l'écran ViewController et existera aussi longtemps que cet écran existe. Il sera vide, car nous n’avons en fait encore rien mis dedans, mais au moins il est prêt à être rempli.

Ce que nous voulons vraiment, c’est ajouter au tableau pictures tous les fichiers qui commencent par "nssl" dans notre boucle. Pour cela, nous devons remplacer le commentaire // this is a picture to load! par le code qui permet d'ajouter chaque image au tableau pictures.

Les tableaux en Swift ont une méthode intégrée appelée append que nous pouvons utiliser pour ajouter les éléments de notre choix. Donc, remplacez le commentaire // this is a picture to load! par ceci :

pictures.append(item)

C'est tout ! Malheureusement, après tout ce travail, notre application ne semblera rien faire lorsque vous appuierez sur Play - vous verrez le même écran blanc que précédemment. Notre code a-t-il fonctionné ou a-t-il simplement échoué en silence ?

Pour le savoir, ajoutez cette ligne de code à la fin de viewDidLoad(), juste avant l'accolade fermante :

print(pictures)

Elle demande à Swift d'afficher le contenu de pictures dans la console de débogage de Xcode. En exécutant le programme dès à présent, vous devriez voir ce texte apparaître au bas de la fenêtre de Xcode : "["nssl0033.jpg", "nssl0034.jpg", "nssl0041.jpg", "nssl0042.jpg", "nssl0043.jpg", "nssl0045.jpg", "nssl0046.jpg", "nssl0049.jpg", "nssl0051.jpg", "nssl0091.jpg"]"

Remarque : iOS aime afficher plein de messages de débogage sans intérêt dans la console de Xcode. Ne vous inquiétez pas si vous voyez beaucoup de texte que vous ne reconnaissez pas, faites-le simplement défiler jusqu’à ce que s'affiche le texte ci-dessus. Si vous le voyez, alors vous êtes prêt à continuer.

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let us know!

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.