Partager via


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 :

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 et XamMac.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 et Xamarin.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. ou MonoMac. 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 nintet nuintnfloat 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 Actionstandard. 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 stringNSString, 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.