[ad_1]

Créez un projet SwiftUI bien documenté, organisé et évolutif à l’aide de l’architecture MVVM qui fera dire « wow » à vos réviseurs de code.

photo par Martin Sanchez sur Unsplash

SwiftUI est le nouveau framework en plein essor construit par Apple, et il est construit sur leur langage de codage open source Swift. Bien qu’il ait encore du rattrapage à faire avec UIKit en termes de fonctionnalités, SwiftUI fournit aux développeurs une syntaxe déclarative pour créer des vues. En conséquence, il peut avoir un beau code évolutif qui crée une belle interface utilisateur.

Passons à la construction d’un projet optimisé.

L’architecture MVVM (modèle, vue, modèle de vue) présente trois principaux types de structure de données :

  • Vues sont des interfaces utilisateur qui affichent les propriétés d’un modèle de vue. L’utilisateur interagit avec la vue, et la vue gère les interactions de l’utilisateur en appelant le modèle de vue.
  • Voir les modèles encapsulez la logique de la vue, y compris les appels d’API, la gestion des événements ou des données et le stockage des propriétés importantes.
  • Des modèles sont représentatifs des données. Ce sont des objets créés à partir des résultats de l’API, utilisés pour contenir des informations utilisateur ou des objets abstraits dans votre application.

Commençons notre projet optimisé en créant un exemple de vue, de modèle de vue et de système de modèles. En cours de route, je partagerai quelques conseils pour vous aider à le garder évolutif et documenté.

Nous allons commencer par le modèle. Puisque vous écrivez en Swift, vous devrez décider d’utiliser une classe ou une structure.

Des classes sont passe-par-référence ; tandis que Structures sont passés par valeur.

Apple vous recommande d’utiliser des structures pour plusieurs raisons, notamment la sécurité de la mémoire et la réduction de la complexité. Cependant, le le choix vous appartient.

Dans mon exemple, j’ai créé un Food modèle qui a un nom et si c’est mon préféré. Je vais l’utiliser pour créer une application qui affiche tous mes aliments préférés.

Il se passe beaucoup de choses ici. Mais notons comment les choses ont été mises en place :

  • La Food struct avait une documentation multiligne avec /** */. Dans la discussion approfondie de la documentation, un lien vers FoodView est fourni en utilisant la notation double backtick.
  • Chaque propriété a une documentation sur une seule ligne avec ///. Chaque méthode a une documentation multi-lignes.
  • UN // MARK: — L’instruction délimite les propriétés et les méthodes. Nous l’utiliserons pour distinguer les propriétés, les méthodes, les initialiseurs, les classes/structures/énumérations imbriquées et d’autres types d’implémentation.
  • Une propriété calculée emoji renvoie un emoji basé sur le nom de l’aliment. Si vous souhaitez afficher du contenu lié uniquement au modèle, il est recommandé d’encapsuler les propriétés ou les fonctions calculées dans la logique de votre modèle. Vous verrez l’avantage de cela quand nous écrivons FoodView.
  • Le modèle a également des méthodes utiles, comme eat().

Et c’est tout! Les modèles sont assez simples. Si vous travaillez avec Codablevous pouvez également implémenter manuellement CodingKeys, encode(to:) et init(from:) dans votre modèle.

Maintenant, notre modèle de vue prendra un tas de Food modèles, et cela nous permettra de les afficher et de les modifier :

Choses à noter ici :

  • FoodViewModel conforme à ObservableObjectnous fournissant @Published wrappers qui nous permettent de maintenir à jour l’état de notre application.
  • j’ai utilisé // MARK: — pour délimiter les propriétés enveloppées et non enveloppées par préférence personnelle.
  • Une propriété publiée allFoods donne accès à tous mes aliments. Un bon endroit pour charger/enregistrer des données comme celle-ci est dans le modèle de vue.
  • toggleFavorite(food:)prend dans un Binding<Food> objet, afin que je puisse mettre à jour le statut préféré de l’aliment via une référence (puisque les structures sont transmises par valeur).

FoodView affichera les aliments préférés de l’utilisateur. Nous allons commencer par une vue défilante qui répertorie un tas d’éléments, affichant des objets alimentaires.

Comme les objets alimentaires sont indépendants, je vais créer un vue de soutien qui affiche uniquement cet objet. J’utilise des vues complémentaires pour que mon body la propriété est agréable, propre et lisible.

Regarde:

Et il affiche :

Notre FoodView, affichant une bascule pour afficher tous les aliments et la liste des articles.

Quelques conseils sur la vue ci-dessus :

  • La // MARK: — le délimiteur sépare les propriétés enveloppées, la vue du corps et les vues de support.
  • J’ai extrait l’élément individuel dans une vue de support pour aider à améliorer la lisibilité et la vitesse de body. L’extraction de vues vers des variables/méthodes facilite également le débogage, car le compilateur SwiftUI a souvent du mal à compiler de grandes vues imbriquées.
  • Les touches finales, comme la mise en majuscule des noms des aliments, sont utilisées dans la vue pour améliorer l’apparence. Il est recommandé d’utiliser des propriétés calculées dans des modèles ou des modèles de vue pour améliorer la lisibilité du code.

Et nous avons terminé. Nous avons configuré notre projet MVVM de base avec quelques optimisations. Construisons là-dessus, en ajoutant quelques détails supplémentaires.

Maintenant, nous avons besoin d’un objet pour faire circuler l’information globale. j’utilise un Global @EnvironmentObject singleton pour gérer cela.

En règle générale, vous souhaiterez stocker les informations utilisées dans votre application dans Global. Dans la plupart de mes applications, je stocke les données utilisateur dans un activeUser propriété. Voici un exemple simple d’un Global classer:

Dans mes vues, j’utilise le code suivant pour définir l’objet d’environnement et le transmettre à ma vue racine :

let global = Global()
...
MyMainRootView().environmentObject(global)

Ensuite, pour accéder à mon objet Global dans toutes mes vues enfants :

/// The Global `EnvironmentObject`.
@EnvironmentObject var global: Global

Pour plus d’informations sur la mise en œuvre d’un EnvironmentObject dans vos vues, consultez cet article Hacking with Swift.

Depuis que j’utilise constamment Global dans mes projets, j’ai créé un extrait de code qui aide à rendre cela plus rapide.

Les extraits de code sont parfaits pour saisir du code pré-écrit avec des espaces réservés facultatifs. Vérifier cet article de Sarunw pour en savoir plus sur la création de vos propres extraits de code dans Xcode.

J’utilise des extraits de code pour ajouter rapidement Global, afficher des modèles ou d’autres propriétés.

Jusqu’à présent, nous avons défini un modèle de vue pour aider à gérer diverses logiques liées à FoodView. Mais de nombreux projets utiliseront plusieurs modèles de vue. Nous aurons donc besoin d’un moyen d’abstraire nos modèles de vue pour obéir à un seul ViewModel protocole.

Une chose que nous voudrons garder à l’esprit lors de la construction de notre ViewModel protocole est notre besoin occasionnel d’accéder à notre Global objet. Idéalement, nous passerions un global instance dans l’initialiseur du modèle de vue.

Cependant, si vous essayez de le faire, vous rencontrerez des problèmes. Vous ne pouvez pas passer global dans l’initialiseur du modèle de vue, comme global est disponible uniquement après les propriétés de la vue, y compris le modèle de vue, ont été initialisées.

Cela signifie que nous devons injecter la global objets en tant que dépendance pour notre modèle de vue. Et puisque nous travaillons sur un protocole de modèle de vue général, nous pouvons coder cette injection de dépendance afin que chaque modèle de vue que nous créons prenne automatiquement en charge global injection:

protocol ViewModel: ObservableObject {  // MARK: - Properties  /// The global instance.
var global: Global? { get set }
}
extension ViewModel { // MARK: - Methods /**
Prepares the view model with the global instance.
- parameter global: The global instance, taken from a `View`
*/
func prepare(with global: Global) {
self.global = global
}
}

C’est le code (avec documentation supplémentaire) que j’utilise pour définir le ViewModel protocole dans tous mes projets.

Ce protocole de modèle de vue équipe une nouvelle méthode, prepare(with:)ce qui vous permet de fournir un Global instance à votre modèle de vue. Appelez-le à l’intérieur onAppear(perform:) et vous pourrez accéder à votre global objet dans votre modèle de vue !

Vous pouvez organiser et structurer votre projet comme vous le souhaitez. Étant donné que notre projet est construit à partir de l’architecture MVVM, nous pouvons organiser son contenu dans les dossiers Model, View Model et View. Le contenu restant peut aller dans d’autres dossiers :

  • Lifecycle dossier, pour les fichiers pertinents pour l’ensemble de l’application, tels que AppDelegate, yourAppou Global .
  • Utilities dossier, pour les méthodes d’assistance, les protocoles supplémentaires, etc.
  • Extensionspour Swift et les extensions de module.
  • Componentspour les petites vues SwiftUI hautement réutilisables (non dépendantes de ViewModel).
  • View Modifierspour les modificateurs de vue personnalisés.
  • Stylespour ButtonStyles, MenuStyles, PickerStyles, TextFieldStylesetc.
  • Enumerationspour les énumérations à l’échelle du projet.
  • Assetssi vous souhaitez regrouper des actifs non compatibles avec le catalogue d’actifs de votre projet.

Voici comment j’ai structuré le projet que nous avons construit dans cet article :

Notre structure de projet. Les modèles, les vues et les modèles de vue sont placés dans leurs dossiers respectifs.

Si vous souhaitez revoir ce qui a été construit, ou si vous souhaitez l’utiliser comme modèle, vous pouvez consulter l’intégralité du projet sur GitHub.

Comme exemple supplémentaire à plus grande échelle, voici comment mon projet personnel Flowductive est structuré :

Ce projet utilise la même architecture MVVM, mais a un code multiplateforme séparé en fonction des besoins Platform et Shared répertoires. Si vous êtes curieux d’écrire du code multiplateforme, j’écrirai des articles concernant le développement multiplateforme dans un futur proche.

Merci d’avoir lu.

[ad_2]

Télécharger ici

Leave a Reply

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Instagram

Ce message d’erreur n’est visible que pour les administrateurs de WordPress

Erreur. Aucun flux trouvé.

Veuillez aller sur la page de réglages d‘Instagram Feed pour connecter votre compte.