La plupart des CV KMP viennent du développement Android. Le candidat connaît Kotlin, les coroutines et Jetpack Compose, et il a ajouté un module partagé à une application existante. Les offres françaises décrivent surtout ce cas : un développeur Android qui crée des modules communs consommés par l'équipe iOS. Plus rarement, le poste couvre toute l'application en Compose Multiplatform, stable sur iOS depuis 2025.
L'expérience réelle se voit du côté iOS. Une personne qui a livré un module partagé sait comment une fonction suspend ou un Flow apparaît dans Swift, pourquoi une exception Kotlin non déclarée fait planter l'app iOS et comment le framework arrive dans Xcode. Celle qui a seulement suivi un tutoriel décrit expect/actual et s'arrête là. Demandez le dernier bug corrigé côté iOS et la façon dont il a été trouvé.
Le build a aussi changé récemment. Le plugin Android dédié aux bibliothèques KMP remplace l'ancien montage avec com.android.library, qui repose sur des API dépréciées depuis AGP 9. L'export Swift, qui évite de passer par Objective-C, est en bêta dans les préversions de Kotlin 2.5. Un candidat à jour en a entendu parler. Le PDF contient l'entretien complet, six axes et un cas de 20 minutes.
Les bibliothèques et outils d'un module KMP partagé
Kotlin Multiplatform et les source sets
Le code est rangé en source sets : commonMain pour ce qui est partagé, androidMain et iosMain pour ce qui dépend de la plateforme. Le mécanisme expect/actual déclare une fonction dans le code commun et la réalise sur chaque plateforme. Un projet bien découpé en contient peu. Une profusion d'expect/actual signale souvent un module mal pensé.
Kotlin/Native et l'interop Swift
Côté iOS, le code Kotlin est compilé en framework natif que Xcode importe. Swift le voit à travers des en-têtes Objective-C, ce qui dégrade certains types : fonctions suspend, Flow, classes scellées, génériques. Des outils comme SKIE ou KMP-NativeCoroutines corrigent une partie de ces défauts. L'export Swift direct est en bêta.
Compose Multiplatform
Le framework d'interface de JetBrains, dérivé de Jetpack Compose, qui permet de partager aussi les écrans. Il est stable sur iOS depuis la version 1.8, sortie en 2025. Beaucoup de projets KMP gardent pourtant SwiftUI côté iOS et ne partagent que la logique. Demandez lequel des deux modèles la personne a pratiqué.
Ktor client et kotlinx.serialization
Le client HTTP multiplateforme de JetBrains, avec un moteur par plateforme (OkHttp sur Android, Darwin sur iOS), et la sérialisation JSON générée à la compilation, sans réflexion. C'est souvent la première brique partagée d'un projet, avec les modèles de données.
SQLDelight ou Room
Pour la base locale. SQLDelight génère du Kotlin typé à partir de requêtes SQL écrites à la main. Room, la bibliothèque Android de Google, fonctionne aussi en multiplateforme depuis sa version 2.7. DataStore couvre les préférences simples.
Coroutines, Flow et Koin
Les coroutines portent l'asynchrone du code partagé, les Flow exposent les données qui changent. Koin est l'injection de dépendances la plus répandue en KMP, car Hilt ne fonctionne que sur Android. Les ViewModel d'AndroidX existent aussi en version multiplateforme.
Gradle et le plugin Android-KMP
Le build passe par Gradle, avec le plugin Kotlin Multiplatform et, pour la cible Android d'une bibliothèque, le plugin com.android.kotlin.multiplatform.library. L'ancien montage avec com.android.library dépend d'API dépréciées dans AGP 9 et appelées à disparaître avec AGP 10. Les compilations iOS, plus longues, pèsent sur la CI.
Distribution vers Xcode
Le framework partagé arrive dans le projet iOS sous forme de XCFramework, par Swift Package Manager, par CocoaPods ou par une tâche Gradle appelée depuis Xcode. Ce choix décide si l'équipe iOS doit installer une JDK et Gradle ou si elle reçoit un binaire déjà compilé.
Les offres KMP en France sont presque toutes des postes Android qui demandent en plus le partage de code avec iOS. Le candidat type a plusieurs années d'Android natif et un ou deux projets KMP. Les profils iOS passés à KMP existent mais restent rares, et ils apportent ce qui manque souvent aux premiers : Xcode, Swift Package Manager, les contraintes de l'App Store. Selon le projet, le poste consiste à introduire KMP dans deux applications natives existantes, module par module, ou à maintenir une application déjà partagée, parfois avec Compose Multiplatform pour l'interface. Il n'existe pas de certification officielle KMP : la preuve passe par le code livré et par les questions techniques.
Six savoir-faire à noter chez un développeur KMP
- Découpage du code commun et expect/actual
- Interop Kotlin, Swift et Objective-C
- Coroutines, Flow et concurrence
- Réseau, sérialisation et base locale
- Build Gradle et intégration Xcode
- Tests multiplateformes et diagnostic
Des questions sur la frontière entre Kotlin et iOS
Chaque question vient avec ce qu'une bonne réponse contient et le signal qui doit vous alerter. Pas besoin d'être technique pour les poser : écoutez si le candidat raconte du vécu.
Question 1 · confirmé
Une fonction suspend du module partagé lève une IOException. Que se passe-t-il dans l'app iOS, et comment l'évitez-vous ?
Une bonne réponseSans annotation, l'exception qui traverse la frontière vers Swift fait planter l'application : Kotlin/Native ne transmet à Swift que les exceptions déclarées. Avec @Throws(IOException::class), la fonction devient throwing côté Swift, ou son completion handler reçoit une erreur, et l'appelant la traite avec do/catch. Les bons profils ajoutent qu'ils préfèrent souvent renvoyer un type résultat, une classe scellée succès ou erreur, plutôt que de laisser fuir des exceptions vers iOS.
Signal d'alerte« Swift attrape l'erreur avec un catch », sans savoir qu'il faut la déclarer côté Kotlin. Ou aucune idée de ce qui se passe hors d'Android.
Question 2 · junior à confirmé
Vous devez lire un identifiant d'installation depuis le code commun. Comment l'écrivez-vous ?
Une bonne réponseUne déclaration expect dans commonMain, fonction ou classe, et une réalisation actual dans androidMain et iosMain qui appelle les API de chaque plateforme, par exemple identifierForVendor côté iOS ou un identifiant généré puis stocké côté Android. Beaucoup préfèrent une interface commune injectée par Koin, réalisée en Kotlin pour Android et parfois en Swift pour iOS, et gardent expect/actual pour les cas simples. Un bon candidat cite aussi les règles de confidentialité des stores sur les identifiants.
Signal d'alerteUn test de plateforme au milieu du code commun, ou la conviction que commonMain peut appeler directement les API Android.
Question 3 · confirmé à senior
Un ViewModel partagé expose un StateFlow. Comment l'écran SwiftUI s'y abonne-t-il, et qui arrête la collecte ?
Une bonne réponseExporté tel quel, le Flow perd son type et n'offre pas d'API Swift naturelle. Les solutions courantes sont SKIE ou KMP-NativeCoroutines, qui le transforment en AsyncSequence ou en publisher, ou un petit wrapper maison avec un callback et une fonction d'annulation. La collecte tourne dans un scope lié au cycle de vie de l'écran, la tâche SwiftUI ou le viewModelScope du ViewModel multiplateforme, et s'arrête quand l'écran disparaît. Sinon le ViewModel et ses requêtes continuent en arrière-plan.
Signal d'alerte« Swift lit le Flow comme sur Android », ou aucune notion d'annulation, avec des collectes qui s'empilent à chaque affichage de l'écran.
Question 4 · senior
L'app doit fonctionner hors ligne et envoyer les modifications au retour du réseau. Que mettez-vous dans le module partagé ?
Une bonne réponseUne base locale partagée, SQLDelight ou Room, qui sert de source pour l'affichage. Une table des modifications en attente, rejouées par le client Ktor au retour du réseau avec un identifiant pour éviter les doublons côté serveur. Une règle de conflit décidée avec le back-end : dernier écrit gagnant, numéro de version ou fusion. Le déclenchement reste natif, WorkManager sur Android et BGTaskScheduler sur iOS, appelés depuis le code de plateforme. L'écran observe la base par un Flow et ne lit jamais le réseau directement.
Signal d'alerteUn simple cache en mémoire, ou la conviction que le code commun peut planifier seul une tâche de fond sur iOS.
Question 5 · confirmé à senior
L'équipe iOS se plaint : chaque build Xcode relance Gradle et prend plusieurs minutes. Que proposez-vous ?
Une bonne réponseSéparer les usages. Pour le travail quotidien de l'équipe iOS, un XCFramework déjà compilé par la CI, versionné et distribué par Swift Package Manager ou un dépôt binaire, consommé sans Gradle. Pour ceux qui travaillent des deux côtés, garder l'intégration directe en ne compilant que la cible du simulateur utilisé, en debug, avec le cache Gradle et la compilation incrémentale de Kotlin/Native. Un bon profil mesure avant d'agir et regarde l'édition des liens du framework, souvent l'étape la plus lente.
Signal d'alerte« C'est normal avec KMP », ou compiler toutes les architectures en release à chaque build de développement.
Recevez la fiche d'entretien complète en PDF
La fiche pour mener l'entretien de bout en bout, prête à imprimer ou à partager avec le manager.
- 30 questions sur 6 axes, avec la bonne réponse, le signal d'alerte et la relance
- Le niveau visé pour chaque question
- Une mise en situation de 20 minutes et ce qu'on attend du candidat
- La grille d'évaluation de 1 à 4, axe par axe
KMP, Compose Multiplatform, Flutter : les interrogations des recruteurs
Un développeur Android peut-il tenir un poste Kotlin Multiplatform ?
C'est le profil le plus courant, à condition qu'il ait déjà livré du code appelé par une app iOS. Kotlin, les coroutines et Compose se transfèrent directement. Ce qui manque souvent : Xcode, la lecture du Swift, la distribution du framework et le comportement de Kotlin/Native. Vérifiez ces points en entretien plutôt que le nombre d'années d'Android. Un profil sans aucune expérience iOS demandera un temps d'adaptation, acceptable si l'équipe iOS peut l'accompagner.
Faut-il exiger Compose Multiplatform dans l'offre ?
Seulement si le projet partage aussi les écrans. Beaucoup d'équipes KMP gardent SwiftUI côté iOS et ne partagent que la logique, et Jetpack Compose suffit alors côté Android. Compose Multiplatform est stable sur iOS depuis 2025, mais il ajoute ses propres sujets : intégration avec la navigation iOS, accessibilité, rendu du texte, taille de l'application. Précisez le modèle retenu dans l'offre, il change le profil recherché.
KMP, Flutter ou React Native : est-ce le même profil ?
Non. Flutter et React Native partagent toute l'application avec leur propre moteur de rendu ou leurs propres composants. KMP part du natif et ne partage que ce qu'on choisit, souvent la logique seule. Un développeur Flutter ne devient pas développeur KMP sans apprendre Kotlin et l'écosystème Android. Le choix de la technologie se fait en amont avec l'équipe technique, et le recrutement suit ce choix.
Quel test technique proposer à un développeur KMP ?
Un exercice court sur un petit module partagé : ajouter un appel Ktor, l'exposer en Flow et montrer son utilisation depuis une vue SwiftUI. Une heure suffit, en direct, avec un commentaire à voix haute. Vous voyez la structure du code commun, la gestion des erreurs et l'aisance côté iOS. Évitez l'application complète à faire chez soi, qui mesure surtout le temps libre du candidat.
Pour structurer vos autres entretiens, consultez aussi nos pages sur les questions d'entretien de recrutement, la méthode de l'entretien structuré et la grille d'évaluation d'entretien.






