Vue d’ensemble de l’API unifiée
L’API unifiée de Xamarin permet de partager du code entre Mac et iOS et de prendre en charge les applications 32 et 64 bits avec le même binaire. L’API unifiée est utilisée par défaut dans les nouveaux projets Xamarin.iOS et Xamarin.Mac.
Important
L’API Xamarin Classic, qui a précédé l’API unifiée, a été dépréciée.
- La dernière version de Xamarin.iOS pour prendre en charge l’API classique (monotouch.dll) était Xamarin.iOS 9.10.
- Xamarin.Mac prend toujours en charge l’API classique, mais elle n’est plus mise à jour. Étant donné qu’elle est déconseillée, les développeurs doivent déplacer leurs applications vers l’API unifiée.
Mise à jour des applications basées sur des API classiques
Suivez les instructions appropriées pour votre plateforme :
- Mettre à jour des applications existantes
- Mettre à jour des applications iOS existantes
- Mettre à jour des applications Mac existantes
- Mettre à jour des applications Xamarin.Forms existantes
- Migrer une liaison vers l’API unifiée
Conseils pour la mise à jour du code vers l’API unifiée
Quelles que soient les applications que vous migrez, case activée ces conseils pour vous aider à effectuer une mise à jour réussie vers l’API unifiée.
Fractionnement de bibliothèque
À partir de ce stade, nos API seront exposées de deux manières :
- API classique : Limité à 32 bits (uniquement) et exposé dans les
monotouch.dll
assemblys etXamMac.dll
. - API unifiée : Prendre en charge le développement 32 et 64 bits avec une seule API disponible dans les
Xamarin.iOS.dll
assemblys etXamarin.Mac.dll
.
Cela signifie que pour les développeurs d’entreprise (ne ciblant pas le App Store), vous pouvez continuer à utiliser les API classiques existantes, car nous les conserverons toujours, ou vous pouvez effectuer une mise à niveau vers les nouvelles API.
Modifications de l’espace de noms
Pour réduire les frictions sur le partage de code entre nos produits Mac et iOS, nous modifions les espaces de noms des API dans les produits.
Nous supprimons le préfixe « MonoTouch » de notre produit iOS et « MonoMac » de notre produit Mac sur les types de données.
Cela simplifie le partage de code entre les plateformes Mac et iOS sans recourir à la compilation conditionnelle et réduit le bruit en haut de vos fichiers de code source.
- API classique : Les espaces de noms utilisent
MonoTouch.
ouMonoMac.
préfixent. - API unifiée : Aucun préfixe d’espace de noms
Valeurs par défaut du runtime
L’API unifiée utilise par défaut le récupérateur de mémoire SGen et le nouveau système de comptage de références pour le suivi de la propriété de l’objet. Cette même fonctionnalité a été transférée vers Xamarin.Mac.
Cela résout un certain nombre de problèmes que les développeurs ont rencontrés avec l’ancien système et facilite également la gestion de la mémoire.
Notez qu’il est possible d’activer New Refcount même pour l’API Classic, mais que la valeur par défaut est conservatrice et n’exige pas que les utilisateurs apportent des modifications. Avec l’API unifiée, nous avons profité de la modification de la valeur par défaut et d’offrir aux développeurs toutes les améliorations en même temps qu’ils refactorisent et retestent leur code.
Modifications de l’API
L’API Unifiée supprime les méthodes dépréciées et il existe quelques instances où des fautes de frappe étaient présentes dans les noms d’API lorsqu’ils étaient liés aux espaces de noms MonoTouch et MonoMac d’origine dans les API classiques. Ces instances ont été corrigées dans les nouvelles API unifiées et devront être mises à jour dans vos applications de composant, iOS et Mac. Voici une liste des plus courantes que vous pourriez avoir :
Nom de la méthode d’API classique | Nom de la méthode d’API unifiée |
---|---|
UINavigationController.PushViewControllerAnimated() |
UINavigationController.PushViewController() |
UINavigationController.PopViewControllerAnimated() |
UINavigationController.PopViewController() |
CGContext.SetRGBFillColor() |
CGContext.SetFillColor() |
NetworkReachability.SetCallback() |
NetworkReachability.SetNotification() |
CGContext.SetShadowWithColor |
CGContext.SetShadow |
UIView.StringSize |
UIKit.UIStringDrawing.StringSize |
Pour obtenir la liste complète des modifications apportées lors du passage de l’API classique à l’API unifiée, consultez notre documentation sur les différences entre l’API classique (monotouch.dll) et l’API unifiée (Xamarin.iOS.dll).
Mise à jour vers Unified
Plusieurs API anciennes/rompues/déconseillées dans classic ne sont pas disponibles dans l’API unifiée . Il peut être plus facile de corriger les CS0616
avertissements avant de commencer votre mise à niveau (manuelle ou automatisée), car vous aurez le [Obsolete]
message d’attribut (partie de l’avertissement) pour vous guider vers l’API appropriée.
Notez que nous publions un diff des modifications apportées à l’API classique et unifiée qui peut être utilisée avant ou après les mises à jour de votre projet. La résolution des appels obsolètes dans Classic est souvent un gain de temps (moins de recherches de documentation).
Suivez ces instructions pour mettre à jour des applications iOS existantes ou des applications Mac vers l’API unifiée. Consultez le reste de cette page et ces conseils pour obtenir des informations supplémentaires sur la migration de votre code.
NuGet
Les packages NuGet qui prenaient auparavant en charge Xamarin.iOS via l’API Classic ont publié leurs assemblys à l’aide du moniker de plateforme Monotouch10 .
L’API unifiée introduit un nouvel identificateur de plateforme pour les packages compatibles : Xamarin.iOS10. Les packages NuGet existants devront être mis à jour pour ajouter la prise en charge de cette plateforme, en les créant par rapport à l’API unifiée.
Important
Si vous avez une erreur au format « Erreur 3 Impossible d’inclure à la fois 'monotouch.dll' et 'Xamarin.iOS.dll' dans le même projet Xamarin.iOS - 'Xamarin.iOS.dll' est référencé explicitement, alors que « monotouch.dll » est référencé par « xxx, Version=0.0.000, Culture=neutral, PublicKeyToken=null » après la conversion de votre application en API unifiées, cela est généralement dû à la présence d’un composant ou d’un package NuGet dans le projet qui n’a pas été mis à jour vers l’API unifiée. Vous devez supprimer le composant/NuGet existant, effectuer une mise à jour vers une version qui prend en charge les API unifiées et effectuer une build propre.
La route vers les 64 bits
Pour plus d’informations sur la prise en charge des applications 32 et 64 bits et des informations sur les frameworks, consultez les considérations relatives à la plateforme 32 et 64 bits.
Nouveaux types de données
Au cœur de la différence, les API Mac et iOS utilisent des types de données spécifiques à l’architecture qui sont toujours 32 bits sur les plateformes 32 bits et 64 bits sur les plateformes 64 bits.
Par exemple, Objective-C mappe le NSInteger
type de données sur int32_t
les systèmes 32 bits et int64_t
sur les systèmes 64 bits.
Pour correspondre à ce comportement, sur notre API unifiée, nous remplaçons les utilisations précédentes de int
(qui dans .NET est défini comme étant toujours System.Int32
) par un nouveau type de données : System.nint
. Vous pouvez considérer le « n » comme signifiant « natif », c’est-à-dire le type entier natif de la plateforme.
Nous introduisons nint
et nuint
nfloat
fournissons également des types de données basés sur eux si nécessaire.
Pour en savoir plus sur ces modifications de type de données, consultez le document Types natifs .
Comment détecter l’architecture des applications iOS
Dans certaines situations, votre application doit savoir si elle s’exécute sur un système iOS 32 bits ou 64 bits. Le code suivant peut être utilisé pour case activée l’architecture :
if (IntPtr.Size == 4) {
Console.WriteLine ("32-bit App");
} else if (IntPtr.Size == 8) {
Console.WriteLine ("64-bit App");
}
Tableaux et System.Collections.Generic
Étant donné que les indexeurs C# attendent un type de int
, vous devrez convertir nint
explicitement les valeurs int
en pour accéder aux éléments d’une collection ou d’un tableau. Par exemple :
public List<string> Names = new List<string>();
...
public string GetName(nint index) {
return Names[(int)index];
}
Ce comportement est attendu, car le cast de int
en nint
est avec perte sur 64 bits, une conversion implicite n’est pas effectuée.
Conversion de DateTime en NSDate
Lors de l’utilisation des API unifiées, la conversion implicite de DateTime
en NSDate
valeurs n’est plus effectuée. Ces valeurs doivent être explicitement converties d’un type à un autre. Les méthodes d’extension suivantes peuvent être utilisées pour automatiser ce processus :
public static DateTime NSDateToDateTime(this NSDate date)
{
// NSDate has a wider range than DateTime, so clip
// the converted date to DateTime.Min|MaxValue.
double secs = date.SecondsSinceReferenceDate;
if (secs < -63113904000)
return DateTime.MinValue;
if (secs > 252423993599)
return DateTime.MaxValue;
return (DateTime) date;
}
public static NSDate DateTimeToNSDate(this DateTime date)
{
if (date.Kind == DateTimeKind.Unspecified)
date = DateTime.SpecifyKind (date, /* DateTimeKind.Local or DateTimeKind.Utc, this depends on each app */)
return (NSDate) date;
}
API et fautes de frappe dépréciées
Dans l’API classique Xamarin.iOS (monotouch.dll), l’attribut [Obsolete]
a été utilisé de deux manières différentes :
- API iOS dépréciée : C’est à ce moment-là qu’Apple vous indique d’arrêter d’utiliser une API, car elle est remplacée par une plus récente. L’API Classique est toujours correcte et souvent nécessaire (si vous prenez en charge l’ancienne version d’iOS).
Cette API (et l’attribut
[Obsolete]
) sont inclus dans les nouveaux assemblys Xamarin.iOS. - API incorrecte Certaines API avaient des fautes de frappe sur leurs noms.
Pour les assemblys d’origine (monotouch.dll et XamMac.dll), nous avons conservé l’ancien code disponible pour des raisons de compatibilité, mais ils ont été supprimés des assemblys d’API unifiées (Xamarin.iOS.dll et Xamarin.Mac)
NSObject sous-classes .ctor(IntPtr)
Chaque NSObject
sous-classe a un constructeur qui accepte un IntPtr
. C’est ainsi que nous pouvons instancier une nouvelle instance managée à partir d’un handle ObjC natif.
Dans le classique, il s’agissait d’un public
constructeur. Toutefois, il était facile d’utiliser cette fonctionnalité à mauvais escient dans le code utilisateur, par exemple, la création de plusieurs instances managées pour un seul instance ObjC ou la création d’un instance managé qui n’aurait pas l’état managé attendu (pour les sous-classes).
Pour éviter ce genre de problèmes, les IntPtr
constructeurs sont désormais protected
dans l’API unifiée , à utiliser uniquement pour la sous-classe. Cela garantit que l’API correcte/sécurisée est utilisée pour créer des instance managées à partir de handles, c’est-à-dire
var label = Runtime.GetNSObject<UILabel> (handle);
Cette API retourne un instance managé existant (s’il existe déjà) ou en crée un (si nécessaire). Il est déjà disponible dans les API classiques et unifiées.
Notez que le .ctor(NSObjectFlag)
est maintenant aussi protected
, mais celui-ci a rarement été utilisé en dehors de la sous-classe.
NSAction remplacée par action
Avec les API unifiées, NSAction
a été supprimé au profit du .NET Action
standard. Il s’agit d’une grande amélioration, car Action
est un type .NET commun, alors que NSAction
était spécifique à Xamarin.iOS. Ils font tous les deux exactement la même chose, mais il s’agissait de types distincts et incompatibles, ce qui a entraîné l’écriture d’un plus grand nombre de code pour obtenir le même résultat.
Par exemple, si votre application Xamarin existante incluait le code suivant :
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (new NSAction (delegate() {
ShowDropDownAnimated (tblDataView);
}));
Il peut maintenant être remplacé par un simple lambda :
UITapGestureRecognizer singleTap = new UITapGestureRecognizer (() => ShowDropDownAnimated(tblDataView));
Auparavant, il s’agirait d’une erreur du compilateur, car un Action
ne peut pas être affecté à NSAction
, mais, étant UITapGestureRecognizer
donné que prend maintenant un Action
au lieu d’un NSAction
, il est valide dans les API unifiées.
Délégués personnalisés remplacés par l’action<T>
Dans l’unité , certains délégués .net simples (par exemple, un paramètre) ont été remplacés par Action<T>
. Par exemple,
public delegate void NSNotificationHandler (NSNotification notification);
peut maintenant être utilisé en tant que Action<NSNotification>
. Cela favorise la réutilisation du code et réduit la duplication de code à la fois dans Xamarin.iOS et dans vos propres applications.
Bool<de tâches> remplacé par Task<Boolean,NSError>>
Dans le classique , certaines API asynchrones retournaient Task<bool>
. Toutefois, certains d’entre eux où doivent utiliser lorsqu’un NSError
faisait partie de la signature, c’est-à-dire que le bool
était déjà true
et que vous deviez intercepter une exception pour obtenir le NSError
.
Étant donné que certaines erreurs sont très courantes et que la valeur de retour n’était pas utile, ce modèle a été modifié en unified pour retourner un Task<Tuple<Boolean,NSError>>
. Cela vous permet de case activée à la fois la réussite et toute erreur qui aurait pu se produire pendant l’appel asynchrone.
NSString et chaîne
Dans quelques cas, certaines constantes ont dû être remplacées par string
NSString
, par exemple. UITableViewCell
Classique
public virtual string ReuseIdentifier { get; }
Unifié
public virtual NSString ReuseIdentifier { get; }
En général, nous préférons le type .NET System.String
. Toutefois, en dépit des recommandations d’Apple, certaines API natives comparent des pointeurs constants (et non la chaîne elle-même) et cela ne peut fonctionner que lorsque nous exposons les constantes en tant que NSString
.
Objective-C Protocoles
Le MonoTouch d’origine ne prenait pas entièrement en charge les protocoles ObjC et certaines API non optimales ont été ajoutées pour prendre en charge le scénario le plus courant. Cette limitation n’existe plus, mais, pour des raisons de compatibilité descendante, plusieurs API sont conservées à l’intérieur monotouch.dll
de et XamMac.dll
.
Ces limitations ont été supprimées et nettoyées sur les API Unifiées. La plupart des modifications ressemblent à ceci :
Classique
public virtual AVAssetResourceLoaderDelegate Delegate { get; }
Unifié
public virtual IAVAssetResourceLoaderDelegate Delegate { get; }
Le I
préfixe signifie qu’une interface unifiée est exposée, au lieu d’un type spécifique, pour le protocole ObjC. Cela facilite les cas où vous ne souhaitez pas sous-classer le type spécifique fourni par Xamarin.iOS.
Cela a également permis à certaines API d’être plus précises et faciles à utiliser, par exemple :
Classique
public virtual void SelectionDidChange (NSObject uiTextInput);
Unifié
public virtual void SelectionDidChange (IUITextInput uiTextInput);
Ces API sont désormais plus faciles pour nous, sans référence à la documentation, et la complétion du code IDE vous fournira des suggestions plus utiles en fonction du protocole/de l’interface.
Protocole NSCoding
Notre liaison d’origine incluait un .ctor(NSCoder) pour chaque type, même s’il ne prenait pas en charge le NSCoding
protocole. Une seule Encode(NSCoder)
méthode était présente dans le NSObject
pour encoder l’objet .
Toutefois, cette méthode ne fonctionne que si le instance conforme au protocole NSCoding.
Sur l’API unifiée, nous avons résolu ce problème. Les nouveaux assemblys ont uniquement le .ctor(NSCoder)
si le type est conforme à NSCoding
. De plus, ces types ont désormais une Encode(NSCoder)
méthode qui est conforme à l’interface INSCoding
.
Impact faible : dans la plupart des cas, cette modification n’affecte pas les applications, car les anciens constructeurs supprimés n’ont pas pu être utilisés.
Autres conseils
D’autres modifications à prendre en compte sont répertoriées dans les conseils de mise à jour des applications vers l’API Unifiée.