Conseils pour la mise à jour du code vers l’API unifiée

Lors de la mise à jour d’anciennes solutions Xamarin vers l’API unifiée, les erreurs suivantes peuvent être rencontrées.

NSInvalidArgumentException impossible de trouver une erreur de storyboard

Il existe un bogue dans la version actuelle de Visual Studio pour Mac qui peut se produire après l’utilisation de l’outil de migration automatisée pour convertir votre projet en API unifiées. Après la mise à jour, si vous recevez un message d’erreur dans le formulaire :

Objective-C exception thrown. Name: NSInvalidArgumentException Reason: Could not find a storyboard named 'xxx' in bundle NSBundle...

Pour résoudre ce problème, recherchez le fichier cible de build suivant :

/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/2.1/Xamarin.iOS.Common.targets

Dans ce fichier, vous devez trouver la déclaration cible suivante :

<Target Name="_CopyContentToBundle"
        Inputs = "@(_BundleResourceWithLogicalName)"
        Outputs = "@(_BundleResourceWithLogicalName -> '$(_AppBundlePath)%(LogicalName)')" >

Ajoutez l’attribut DependsOnTargets="_CollectBundleResources" à celui-ci. Comme ceci :

<Target Name="_CopyContentToBundle"
        DependsOnTargets="_CollectBundleResources"
        Inputs = "@(_BundleResourceWithLogicalName)"
        Outputs = "@(_BundleResourceWithLogicalName -> '$(_AppBundlePath)%(LogicalName)')" >

Enregistrez le fichier, redémarrez Visual Studio pour Mac et effectuez une propre et régénérez votre projet. Un correctif pour ce problème doit être publié par Xamarin sous peu.

Astuces utiles

Après avoir utilisé l’outil de migration, vous pouvez toujours obtenir certaines erreurs du compilateur nécessitant une intervention manuelle. Voici quelques éléments qui doivent être corrigés manuellement :

  • La comparaison enumde s peut nécessiter un (int) cast.

  • NSDictionary.IntValue retourne maintenant un nint, il existe un Int32Value qui peut être utilisé à la place.

  • nfloat et nint les types ne peuvent pas être marqués const; static readonly nint est une alternative raisonnable.

  • Les éléments utilisés directement dans l’espace MonoTouch. de noms sont désormais généralement dans l’espace ObjCRuntime. de noms (par exemple : MonoTouch.Constants.Version est maintenant ObjCRuntime.Constants.Version).

  • Le code qui sérialise les objets peut s’interrompre lors de la tentative de sérialisation nint et nfloat de types. Veillez à case activée votre code de sérialisation fonctionne comme prévu après la migration.

  • Parfois, l’outil automatisé manque du code dans #if #else les directives du compilateur conditionnel. Dans ce cas, vous devez effectuer les correctifs manuellement (voir les erreurs courantes ci-dessous).

  • Les méthodes exportées manuellement à l’aide [Export] de l’outil de migration peuvent ne pas être corrigées automatiquement par l’outil de migration, par exemple dans ce code snippert, vous devez mettre à jour manuellement le type de retour vers nfloat:

    [Export("tableView:heightForRowAtIndexPath:")]
    public nfloat HeightForRow(UITableView tableView, NSIndexPath indexPath)
    
  • L’API unifiée ne fournit pas de conversion implicite entre NSDate et .NET DateTime, car elle n’est pas une conversion sans perte. Pour éviter les erreurs liées à DateTimeKind.Unspecified la conversion du .NET DateTime en local ou UTC avant la conversion en NSDate.

  • Objective-C Les méthodes de catégorie sont désormais générées en tant que méthodes d’extension dans l’API unifiée. Par exemple, le code utilisé précédemment UIView.DrawString référencerait NSString.DrawString désormais dans l’API unifiée.

  • Le code utilisant des classes AVFoundation avec VideoSettings doit changer pour utiliser la WeakVideoSettings propriété. Cela nécessite un Dictionary, qui est disponible en tant que propriété sur les classes de paramètres, par exemple :

    vidrec.WeakVideoSettings = new AVVideoSettings() { ... }.Dictionary;
    
  • Le constructeur NSObject .ctor(IntPtr) a été remplacé par public par protégé (pour empêcher une utilisation incorrecte).

  • NSAction a été remplacé par le .NET Actionstandard . Certains délégués simples (paramètre unique) ont également été remplacés par Action<T>.

Pour finir, reportez-vous aux différences d’API unifiée v Classic pour rechercher les modifications apportées aux API dans votre code. La recherche de cette page vous aidera à trouver les API classiques et à ce qu’elles ont été mises à jour.

Remarque

L’espace MonoTouch.Dialog de noms reste le même après la migration. Si votre code utilise MonoTouch.Dialog, vous devez continuer à utiliser cet espace de noms - ne changez MonoTouch.Dialog pas à Dialog!

Erreurs courantes du compilateur

D’autres exemples d’erreurs courantes sont répertoriés ci-dessous, ainsi que la solution :

Erreur CS0012 : Le type « MonoTouch.UIKit.UIView » est défini dans un assembly qui n’est pas référencé.

Correctif : cela signifie généralement que le projet fait référence à un composant ou un package NuGet qui n’a pas été généré avec l’API unifiée. Vous devez supprimer et rajouter tous les composants et packages NuGet. Si cela ne résout pas l’erreur, la bibliothèque externe peut ne pas encore prendre en charge l’API unifiée.

Erreur MT0034 : Impossible d’inclure « monotouch.dll » et « Xamarin.iOS.dll » dans le même projet Xamarin.iOS : « Xamarin.iOS.dll » est référencé explicitement, tandis que « monotouch.dll » est référencé par « Xamarin.Mobile, Version=0.6.3.0, Culture=neutral, PublicKeyToken=null ».

Correctif : supprimez le composant qui provoque cette erreur et réinscrire le projet.

Erreur CS0234 : Le type ou le nom de l’espace de noms « Foundation » n’existe pas dans l’espace de noms « MonoTouch ». Vérifiez qu'il ne manque aucune référence d'assembly.

Correctif : L’outil de migration automatisée dans Visual Studio pour Mac doit mettre à jour toutes les MonoTouch.Foundation références, Foundationmais dans certains cas, ces derniers devront être mis à jour manuellement. Des erreurs similaires peuvent apparaître pour les autres espaces de noms précédemment contenus dans MonoTouch, par UIKitexemple .

Erreur CS0266 : Impossible de convertir implicitement le type 'double' en 'System.float'

Correctif : modifier le type et effectuer un cast sur nfloat. Cette erreur peut également se produire pour les autres types avec des équivalents 64 bits (par nintexemple, , )

nfloat scale = (nfloat)Math.Min(rect.Width, rect.Height);

Erreur CS0266 : Impossible de convertir implicitement le type « CoreGraphics.CGRect » en « System.Drawing.RectangleF ». Une conversion explicite existe (un cast est-il manquant ?)

Correctif : remplacez les instances RectangleFCGRectpar , SizeF par CGSizeet PointF par CGPoint. L’espace de noms using System.Drawing; doit être remplacé using CoreGraphics; par (s’il n’est pas déjà présent).

erreur CS1502 : La meilleure correspondance de méthode surchargée pour « CoreGraphics.CGContext.SetLineDash(System.nfloat, System.nfloat[]) » contient certains arguments non valides

Correctif : Modifiez le type de tableau en nfloat[] cas de conversion Math.PIexplicite et explicite.

grphc.SetLineDash (0, new nfloat[] { 0, 3 * (nfloat)Math.PI });

Erreur CS0115 : « WordsTableSource.RowsInSection(UIKit.UITableView, int) » est marquée comme remplacement, mais aucune méthode appropriée n’est trouvée pour remplacer

Correctif : remplacez la valeur de retour et les types de nintparamètres par . Cela se produit généralement dans les remplacements de méthode tels que ceux sur UITableViewSource, y compris RowsInSection, NumberOfSections, GetHeightForRow, TitleForHeader, GetViewForHeaderetc.

public override nint RowsInSection (UITableView tableview, nint section) {

Erreur CS0508 : : WordsTableSource.NumberOfSections(UIKit.UITableView)le type de retour doit être « System.nint » pour correspondre au membre substitué UIKit.UITableViewSource.NumberOfSections(UIKit.UITableView)

Correction : Lorsque le type de retour est modifié nint, convertissez la valeur de retour en nint.

public override nint NumberOfSections (UITableView tableView)
{
    return (nint)navItems.Count;
}

Erreur CS1061 : Le type « CoreGraphics.CGPath » ne contient pas de définition pour « AddElipseInRect »

Correctif : Correction de l’orthographe à AddEllipseInRect. Les autres modifications de nom sont les suivantes :

  • Remplacez « Color.Black » par NSColor.Black.
  • Remplacez MapKit « AddAnnotation » par AddAnnotations.
  • Remplacez AVFoundation « DataUsingEncoding » par Encode.
  • Remplacez AVFoundation « AVMetadataObject.TypeQRCode » par AVMetadataObjectType.QRCode.
  • Remplacez AVFoundation « Video Paramètres » par WeakVideoSettings.
  • Remplacez PopViewControllerAnimated par PopViewController.
  • Remplacez CoreGraphics « CGBitmapContext.SetRGBFillColor » par SetFillColor.

Erreur CS0546 : impossible de remplacer, car « MapKit.MKAnnotation.Coordinate » n’a pas d’accesseur set substituable (CS0546)

Lors de la création d’une annotation personnalisée en sous-classe MKAnnotation, le champ De coordonnées n’a pas de setter, seul un getter.

Correctif

  • Ajouter un champ pour effectuer le suivi de la coordonnée
  • renvoyer ce champ dans le getter de la propriété Coordinate
  • Remplacer la méthode SetCoordinate et définir votre champ
  • Appeler SetCoordinate dans votre ctor avec le paramètre de coordonnées transmis

Celui-ci doit se présenter comme suit :

class BasicPinAnnotation : MKAnnotation
{
    private CLLocationCoordinate2D _coordinate;

    public override CLLocationCoordinate2D Coordinate
    {
        get
        {
            return _coordinate;
        }
    }

    public override void SetCoordinate(CLLocationCoordinate2D value)
    {
        _coordinate = value;
    }

    public BasicPinAnnotation (CLLocationCoordinate2D coordinate)
    {
        SetCoordinate(coordinate);
    }
}