View Protocol est le protocole fondamental de SwiftUI auquel tout composant d'interface visuelle doit se conformer. Selon Apple Developer Documentation, 2024, View définit un contrat unique : une structure ou une classe implémentant ce protocole doit fournir une propriété calculée body. Grâce à ce protocole, SwiftUI construit toute la hiérarchie des écrans, des simples étiquettes de texte aux structures de navigation complexes.
Points clés
View Protocol est le protocole central de SwiftUI qui définit comment tout élément visuel décrit son contenu. Contrairement à UIKit, où chaque élément hérite de UIView via des classes, SwiftUI utilise une approche orientée protocole : tout type conforme au protocole View peut être affiché à l'écran.
Le protocole View exige l'implémentation d'une seule propriété calculée body qui retourne un contenu. Cependant, derrière cette simplicité se cache un puissant système de composition : body peut retourner tout type conforme à View, y compris des primitives (Text, Image, Button), des conteneurs (VStack, HStack, ZStack) et des composants composites personnalisés.
Selon WWDC 2023, plus de 95 % de tous les écrans dans les applications SwiftUI sont construits par la composition de structures implémentant le protocole View. Cela fait du View Protocol le fondement de toute l'architecture SwiftUI.
SwiftUI exige que View soit un value type (struct), et non une classe. C'est une décision architecturale clé : les value types ont une durée de vie prévisible, pas d'état mutable partagé et permettent à SwiftUI de déterminer efficacement quelles parties de la hiérarchie ont changé et nécessitent un réaffichage.
Si vous essayez de faire de View une classe, le compilateur générera une erreur : le protocole View hérite du protocole DynamicViewProperty, qui exige une sémantique de valeur. Les classes peuvent se conformer à View, mais cela brise l'approche idiomatique et fait perdre les avantages des mises à jour automatiques.
body est la seule exigence obligatoire du protocole View. C'est une propriété calculée qui retourne le contenu affiché à l'écran. Le type de retour est some View, ce qui signifie « un type conforme à View, qui sera déterminé par le compilateur ».
struct GreetingView: View {
var name: String
var body: some View {
VStack {
Text("Hello, \(name)!")
.font(.title)
.foregroundColor(.blue)
Button("Start") {
print("Button pressed")
}
}
}
}
Comment body fonctionne : SwiftUI appelle body chaque fois que l'état de l'application change et qu'un réaffichage est nécessaire. Le framework compare l'arbre de Views nouveau avec l'ancien et applique uniquement les changements nécessaires (diffing). C'est une approche entièrement déclarative — vous décrivez ce qui doit être affiché, et SwiftUI se charge de l'implémenter.
Un détail important : body ne doit pas avoir d'effets secondaires. Il est appelé plusieurs fois pendant la durée de vie de l'application, et si body modifie un état externe, cela entraîne un comportement imprévisible. Pour les effets secondaires, utilisez task, onChange ou DispatchQueue.
SwiftUI impose une restriction : body ne peut retourner qu'un seul élément racine. Si vous devez afficher plusieurs éléments au même niveau, enveloppez-les dans un conteneur — VStack, HStack, ZStack ou Group. Avec l'introduction de @ViewBuilder, cette limitation est devenue moins perceptible, mais conceptuellement body retourne toujours une seule View.
some View est la syntaxe de type opaque (opaque type) introduite dans Swift 5.1 spécifiquement pour SwiftUI. Elle signifie qu'une fonction ou propriété retourne un type concret conforme au protocole View, mais le code appelant ne sait pas et n'a pas besoin de savoir quel type exact est retourné.
Le compilateur Swift fixe le type concret à la compilation pour chaque implémentation de body, mais le cache du monde extérieur. Cela permet à SwiftUI d'optimiser la hiérarchie de Views en connaissant les types exacts de tous les composants, tout en donnant au développeur la flexibilité de modifier l'implémentation sans changer la signature.
struct ContentView: View {
var body: some View {
Text("Hello, World!") // Compiler knows this is Text
}
}
Pourquoi some View et pas simplement View ? Si body retournait simplement View (en tant que protocole), SwiftUI ne pourrait pas déterminer le type concret à la compilation. Cela ajouterait une surcharge d'encapsulation dans un conteneur existentiel. some View donne au compilateur suffisamment d'informations pour l'optimisation tout en conservant la flexibilité du protocole.
La limitation principale est que body doit retourner le même type. Vous ne pouvez pas retourner Text dans une branche d'une condition et Image dans une autre sans wrappers spéciaux (AnyView, Group ou @ViewBuilder). Le compilateur vérifie cela à la compilation : tous les chemins de retour possibles doivent avoir le même type.
Pour contourner cette limitation, on utilise @ViewBuilder (crée un seul type TupleView), Group (qui retourne également un seul type) ou AnyView (efface le type mais ajoute de la surcharge). AnyView ne doit être utilisé que lorsque les autres options ne sont pas possibles, car il désactive les optimisations de SwiftUI.
@ViewBuilder est un result builder dont l'annotation permet d'assembler plusieurs Views en une seule composition sans conteneurs imbriqués. @ViewBuilder enveloppe automatiquement plusieurs expressions dans un tuple (TupleView) ou applique une logique conditionnelle (If / else / switch) avec le type de retour correct.
struct DashboardView: View {
var isLoggedIn: Bool
@ViewBuilder
var body: some View {
if isLoggedIn {
Text("Welcome!")
.font(.largeTitle)
ProfileCard()
} else {
LoginButton()
.padding()
}
}
}
Comment @ViewBuilder fonctionne : le compilateur transforme chaque bloc de code dans @ViewBuilder en appels aux méthodes statiques buildBlock, buildEither, buildOptional, etc. Si un bloc contient plusieurs expressions, elles sont enveloppées dans TupleView. Si un bloc contient une logique conditionnelle, le compilateur génère ConditionalContent, cachant le type de la branche.
@ViewBuilder impose une limitation : jusqu'à 10 éléments par bloc (limitation de TupleView). Si vous devez assembler plus de dix éléments, utilisez Group, ForEach ou divisez en sous-composants. Cette limitation existe parce que Swift génère une surcharge séparée de buildBlock pour chaque arité de 1 à 10.
La composition est un principe clé de SwiftUI : les interfaces complexes sont construites à partir de petits composants View réutilisables. Chaque composant implémente le protocole View et est responsable de sa partie de l'écran. Les modificateurs (font, padding, foregroundColor) sont appliqués à une View et retournent une nouvelle View avec des paramètres modifiés.
Les modificateurs dans SwiftUI ne sont pas des mutations, mais la création d'un nouveau wrapper autour de la View originale. Chaque modificateur retourne un nouveau type (ModifiedContent), permettant à SwiftUI de construire un arbre de modificateurs et de ne réafficher efficacement que les parties modifiées. L'ordre d'application des modificateurs est important : des ordres différents produisent des résultats visuels différents.
Text("Hello, SwiftUI!")
.font(.title) // ModifiedContent
.padding() // ModifiedContent<..., PaddingModifier>
.background(.yellow) // ModifiedContent<..., BackgroundModifier>
.cornerRadius(8) // ModifiedContent<..., CornerRadiusModifier>
Optimisation des performances : SwiftUI ne compare pas les valeurs concrètes des Views mais leur identité via le mécanisme d'identité (id, ForEach, identité stable des structures). Si la structure de la View n'a pas changé, body n'est pas appelé. Ceci est réalisé par la comparaison Equatable et le mécanisme PreferenceKey pour faire remonter les données dans la hiérarchie.
Pour une composition efficace, il est recommandé de diviser les écrans complexes en sous-composants indépendants, chacun avec son propre état minimal. Cela permet à SwiftUI de ne réafficher que les parties modifiées de la hiérarchie, et non l'écran entier.
Foire aux questions
View Protocol est le protocole de base de SwiftUI auquel tout composant affiché doit se conformer. Il nécessite une seule propriété calculée body qui retourne le contenu. Tous les éléments standard de SwiftUI — Text, Button, Image, VStack — implémentent ce protocole.
SwiftUI utilise la sémantique de valeur (value semantics) pour des mises à jour prévisibles de l'interface. Les structures n'ont pas d'état mutable partagé, ce qui permet à SwiftUI de comparer efficacement l'ancienne et la nouvelle hiérarchie de Views et de ne réafficher que les éléments modifiés. Les classes brisent cette optimisation.
body retourne some View — un type opaque qui cache l'implémentation concrète. Il retourne en fait tout type conforme à View : Text, Image, VStack, structures personnalisées. Le compilateur fixe le type concret à la compilation pour l'optimisation.
some View est un type opaque dont le type concret est fixé à la compilation. AnyView est un effacement de type (type erasure) qui enveloppe toute View dans un conteneur unique. some View est plus efficace ; AnyView ajoute de la surcharge et n'est utilisé que lorsqu'un changement de type dynamique est nécessaire.
Jusqu'à 10 éléments — c'est la limitation de TupleView, qui génère buildBlock pour les arités de 1 à 10. Si vous avez besoin de plus d'éléments, utilisez Group, ForEach, List ou divisez en sous-composants. Cette limitation existe au niveau du compilateur Swift.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi