> ## Content Index
> Fetch the complete content index at: https://www.sfeir.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Rappel des nouveautés SwiftUI pour iOS 16
- URL: https://www.sfeir.dev/mobile/rappel-nouveautes-ios16-swiftui/
- Published: 2024-02-16T10:18:36.000Z
- Updated: 2024-02-16T10:18:36.000Z
- Description: L'année dernière, iOS 16 a introduit de nombreuses innovations avec SwiftUI. Une petite piqûre de rappel pourrait être utile !
- Author: Arnaud Le Bourblanc
- Tags: Mobile, iOS, SwiftUI

**iOS 17** est désormais disponible depuis bientôt quatre mois, avec son lot de nouveautés. Vous êtes cependant potentiellement dans la même situation que bon nombre d’autres développeurs iOS : vous ne pouvez pas les embarquer dans vos applications en production. Vous avez néanmoins peut-être eu la chance de passer tout de même la version minimale de vos apps à **iOS 16**. Dans ce cas, cet article est fait pour vous puisqu'il rappelle les nouveautés principales de cette version du côté de **SwiftUI**.

## De nombreuses **nouveautés**

### **AnyLayout**

**AnyLayout** est une nouvelle vue dite conteneur qui aura pour but de pouvoir dynamiquement passer d’un type de layout à un autre. Par exemple, passer d’une **VStack** à une **HStack**. Son atout principal est de ne pas détruire le “**state**” de son contenu lors du changement de layout. Précédemment, la mécanique classique aurait été d’utiliser un if/else pour passer d’une HStack à une VStack, comme par exemple dans le cas de l’accessibilité et de l’augmentation de la taille des polices d’écriture. Le problème dans ce cas est que le passage d’un état à l’autre nous ferait perdre le “**state**” de notre contenu étant donné que l’on serait en train de supprimer. De plus, le fait d'ajouter un nouveau layout lors de chaque transition **redessinerait alors le contenu**. En utilisant AnyLayout on se débarrasse de cet inconvénient tout en gardant la même logique d’affichage.

L’utilisation d’AnyLayout est relativement simple comme on peut le voir avec cet exemple :

```swift
struct DynamicLayoutExample: View {

	@Environment(\\.dynamicTypeSize) var dynamicTypeSize

	var body: some View {
		let layout = dynamicTypeSize <= .medium ? AnyLayout(HStackLayout()) : AnyLayout(VStackLayout())
		
		return layout {
			Text("Un label")
			Text("Un second label")
		}
	} 
}

```

### **refreshable()**

refreshable est un **view modifier** déjà présent depuis iOS 15\. Il n’était cependant réellement utilisable que pour la vue **List**. Il est désormais possible d’ajouter ce view modifier sur une **ScrollView**, permettant de mettre en place plus facilement cette gesture longtemps oubliée par les différentes versions de **SwiftUI**. Si vous le ne le connaissiez pas avant, le view modifier prend un block de code en paramètre, il sera exécuté à chaque fois que l’utilisateur demandera un rafraîchissement avec le geste du pull-to-refresh.

```swift
ScrollView {
	contenu
}.refreshable {
	actualiserContenu()
}

```

### **L’affichage des bottomSheets**

Les modales de **SwiftUI** ont droit à de nombreuses améliorations, que ce soit sur leur visuel ou sur la façon dont elles sont présentées. Un article a déjà été dédié sur le sujet pour les [nouveautés d’iOS 16.0](https://www.sfeir.dev/mobile/ios-16-dessine-moi-une-modale/). Si vous souhaitez allez plus loin un second article recense quant à lui les nouveautés liés à [iOS 16.4 sur les modales](https://www.sfeir.dev/mobile/ios-16-4-une-modale-de-plus-en-plus-customisable/).

### **SwiftCharts**

Grande nouveauté d’**iOS 16**, l’arrivée des **graphes** pour SwiftUI. Plus besoin d’utiliser une librairie tierce pour intégrer la plupart de vos graphes. Je dis la plupart car il manque certains types de graphes très communs comme notamment le type **PieChart** qui ne sera rajouté qu’à partir de la version SwiftUI d’iOS 17\. Vous aurez cependant déjà assez d’éléments entre les mains pour créer des graphes riches, customisés, interactifs. Ne passez pas à côté de cette nouvelle API made in Apple si le besoin se présente.

![Exemples de graphes créés avec SwiftCharts](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2024/01/swiftcharts.png)

Exemples de graphes créés avec SwiftCharts

### Autres **vues**

- **Table** présente des données sous **la forme d’un tableau** comme on pourrait les retrouver dans un tableur. On définira ainsi les différentes **colonnes** à partir d’un modèle de données et de ses propriétés. Il est possible de sélectionner des lignes, de les ordonner ou encore de définir un aspect particulier selon le format du device utilisé. Il est important de noter que la vue Table a tout son intérêt si on souhaite l’intégrer pour une application sur **Mac** ou sur **iPad** mais se retrouvera un peu plus limitée pour un iPhone. Au format portrait, une Table sur **iPhone** n’affichera que sa première colonne.

![Exemple d'une Table avec 3 colonnes](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2024/01/table-1.png)

Exemple d'une Table avec 3 colonnes

- **Grid** a pour but de représenter votre contenu sous la forme d’une grille à deux dimensions. Son utilisation est assez basique. Il suffit de lui fournir des sous-vues appelées **GridRow** qui contiendront un certain nombre de sous-vues qui représenteront chacune une colonne. Sur le papier on pourrait se dire qu’il n’y a rien de nouveau et que l’on pourrait faire cela facilement avec une combinaison de **VStack** et de **HStack**. Point noir de cette solution, chacune de vos lignes ne prend pas en compte les autres et notamment la largeur des sous-vues. La vue **Grid** permet d’avoir un contenu dont chaque élément se retrouve dans une colonne dont la largeur est définie par son élément le plus large, alignant ainsi tous nos éléments verticalement.

![Exemple d'une Grid dont les colonnes s'ajustent avec la taille des textes](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2024/01/grid.png)

Exemple d'une Grid dont les colonnes s'ajustent avec la taille des textes

- **ShareLink** permet de partager du contenu facilement. Précédemment, il fallait écrire beaucoup de code pour pouvoir partager ne serait-ce que du texte avec notamment un bridge vers **UIKit** pour utiliser **UIActivityViewController**. ShareLink a pour rôle, à la fois d’être un bouton et d'être celui qui sera responsable de présenter la modale native de partage. L’élément le plus important sera l’élément que vous lui donnez pour être partager. Cet élément devra implémenter le protocol **Transferable**. Plusieurs types natifs le font déjà (**String, Data, URL**, ...), vous pourrez également le faire sur vos propres modèles de données.

![Représentation de la vue ShareLink dans son plus simple appareil](https://storage.ghost.io/c/0b/31/0b31478e-a66a-46f1-8c34-d44388e21192/content/images/2024/01/sharelink.png)

Représentation de la vue ShareLink dans son plus simple appareil

- **MultiDatePicker** vient simplement ajouter de la multi sélection à la vue **DatePicker** déjà existante. Son utilisation se rapproche énormément de celle de DatePicker avec notamment la possibilité de spécifier une période sur laquelle sélectionner les différentes dates.

### **Navigation**

La navigation au sein d’une application SwiftUI se faisait précédemment en utilisant la vue **NavigationView** et en utilisant le view modifier **navigationViewStyle()** pour spécifier le style de navigation (stack ou columns). Désormais, ce sont deux nouvelles vues qui seront à utiliser, **NavigationStack** et **NavigationSplitView**.  
Le passage d’un écran à un autre a également été mis à jour. Si pour naviguer vers un nouvel écran vous utilisez des booléens pour activer une **NavigationLink,** alors le view modifier **navigationDestination(isPresented:)** va vous intéresser. Il vous permet de passer des NavigationLinks en gardant la logique d’un flag mis à jour pour afficher des nouveaux écrans et avec une syntaxe claire et assimilable facilement.  
**Apple** propose un tutoriel pour migrer vers les nouveaux types de navigation, la vue **NavigationView** étant désormais marqué comme “**deprecated**”.