Staty: Changement d’état de View dans l’architecture MVVM

Il existe de nombreux articles sur l’implémentation de la machine à états dans une application iOS, mais ils ne prennent pas en compte une chose spécifique à iOS – la transition vers un état peut prendre un certain temps et pendant qu’elle achève la transition vers un autre état peut ne pas être être possible.

Considérez la situation suivante.
Votre vue affiche un contenu (appelons-le l’état C). Vous voulez maintenant afficher le chargement lorsque vous effectuez un appel d’API (il peut s’agir d’un simple ActivityIndicatorView ou d’un contrôleur que vous avez créé à cet effet), vous passez donc de l’état à l’état Chargement et votre vue reflète maintenant cet état. Considérez ensuite que l’API a renvoyé une erreur, que vous souhaitez représenter comme une alerte iOS native. Si votre état de chargement est représenté via un contrôleur, il doit être complètement ignoré avant de pouvoir afficher l’alerte, vous devriez donc envisager d’ajouter une logique supplémentaire pour gérer ce type de transitions.

Dans cet article, je propose ma solution pour basculer entre les états, qui peut être facilement étendue, modifiée et réutilisée.

Architecture

Commençons par le protocole State. L’État doit être capable de se représenter sur la cible et de se disposer. De plus, nous fournirons à tout État un délégué, je l’expliquerai ensuite.

Comme nous parlons de MVVM, il est clair qu’un modèle de vue aura sa variable d’état. Évidemment, la vue l’observera. Pour le représenter avec des protocoles, ajoutons le code suivant:

Tout modèle de vue qui souhaite utiliser des états confirmera à StateDrivenViewModel.

Voyons le protocole correspondant pour la vue:

Ici, je fournis également à UIViewController la méthode bindWithState () afin de ne pas répéter ce code dans tous les contrôleurs de vue. Cette méthode peut également être ajoutée pour n’importe quelle vue que vous voulez (c’est-à-dire que vous pouvez étendre UITableViewCell).

Pour l’instant, vous pouvez avoir une structure de base: View observe la variable d’état de son ViewModel et y appelle la méthode enterOn.
Cette méthode peut être implémentée dans chaque état à l’aide du paramètre cible fourni. Cependant, je recommande une meilleure approche: utilisez le modèle de stratégie pour fournir à State la stratégie correspondante à l’aide de StateStrategyProvider que la cible (c’est souvent une vue) implémentera.

Créons par exemple LoadingState:

Comme vous pouvez le voir, je déclare également LoadingStateStrategy qui doit pouvoir afficher et masquer le chargement et LoadingStateStrategyProvider qui doit fournir un objet qui implémente le protocole LoadingStateStrategy. Enfin, je fournis l’implémentation par défaut du fournisseur pour UIViewController, qui retournera une stratégie IndicatorView simple. Regardons la stratégie:

J’ajoute intensément une animation en masquant l’indicateur pour vous montrer comment il sera géré.

Enfin, le joueur le plus important: StateController. StateController gérera toutes les transitions de la manière que vous définissez.

Comme vous pouvez le voir, le contrôleur délègue également à son observateur lorsqu’un état change.

Passons à la partie la plus intéressante: une implémentation du contrôleur qui utilise la file d’attente pour faire des transitions consécutives:

Lorsqu’un état délègue sa sortie, le contrôleur la retire de la file d’attente et invoque l’état suivant dans la file d’attente. S’il n’y a pas d’état suivant, l’état sortant ne sera pas retiré de la file d’attente pour suivre l’état actuel. La classe de file d’attente est juste une classe d’assistance, qui peut être trouvée dans le référentiel via le lien que j’ai fourni à la fin de l’article. Notez que vous pouvez implémenter n’importe quelle logique personnalisée: c’est-à-dire rejeter la transition, etc.

Exemple

Dans cette partie, je donne un exemple simple d’utilisation de cette approche.

Tout d’abord, créons un modèle de vue qui implémente StatyViewModel (juste un alias de type pour StateDrivenViewModel & amp; CurrentStateObserver):

Après que sa vue appellera la méthode de configuration, le contrôleur d’état de la classe BasicStateController sera initialisé et le modèle passera à l’état de chargement, après 1 seconde, nous passerons à trois états d’affilée. Vous verrez que toutes ces transitions seront gérées consécutivement.

Voici une vue qui dans cet exemple est un simple ViewController:

Tout ce que nous avons à faire est d’accepter le protocole StateAwareView pour pouvoir observer l’état, puis d’implémenter des protocoles fournisseur pour les états correspondants que nous voulons représenter. Ici, nous n’avons rien à implémenter car nous avons fourni une sous-classe UIViewController avec une implémentation par défaut. Notez que vous pouvez injecter n’importe quelle stratégie dans un état simplement en la fournissant dans la méthode correspondante ou créer Factory qui le fera etc.

Avantages

Essayez-le!

Lien GitHub: https://github.com/IsaAliev/StatyApp