Tipy pro aktualizaci kódu na Unified API

Při aktualizaci starších řešení Xamarinu na sjednocené rozhraní API se můžou zobrazit následující chyby.

Chyba NSInvalidArgumentException nenašla chybu scénáře

V aktuální verzi Visual Studio pro Mac může dojít k chybě, ke které může dojít po použití nástroje pro automatizovanou migraci k převodu projektu na sjednocená rozhraní API. Pokud se po aktualizaci ve formuláři zobrazí chybová zpráva:

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

Pokud chcete tento problém vyřešit, vyhledejte následující cílový soubor sestavení:

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

V tomto souboru potřebujete najít následující cílovou deklaraci:

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

A přidejte DependsOnTargets="_CollectBundleResources" do něj atribut. Nějak tak:

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

Uložte soubor, restartujte Visual Studio pro Mac a proveďte čisté a opětovné sestavení projektu. Brzy by měl Xamarin vydat opravu tohoto problému.

Užitečné Tipy

Po použití nástroje pro migraci může dojít k chybám kompilátoru vyžadujících ruční zásah. Mezi některé věci, které můžou být potřeba opravit ručně, patří:

  • Porovnání enummůže vyžadovat (int) přetypování.

  • NSDictionary.IntValue nyní vrátí hodnotu nint, je Int32Value k dispozici místo toho, kterou lze použít.

  • nfloat a nint typy nelze označovat const; static readonly nint je rozumnou alternativou.

  • Věci, které se dřív používaly přímo v MonoTouch. oboru názvů, jsou teď obecně v ObjCRuntime. oboru názvů (např. MonoTouch.Constants.Version teď).ObjCRuntime.Constants.Version

  • Kód, který serializuje objekty může přerušit při pokusu o serializaci nint a nfloat typy. Po migraci zkontrolujte, jestli kód serializace funguje podle očekávání.

  • V některých případech automatizovaný nástroj vynechá kód uvnitř #if #else direktiv podmíněného kompilátoru. V takovém případě budete muset provést opravy ručně (viz níže uvedené běžné chyby).

  • Ručně exportované metody používající [Export] nástroj pro migraci nemusí být automaticky opraveny nástrojem pro migraci, například v tomto výsuvku kódu je nutné ručně aktualizovat návratový typ na nfloat:

    [Export("tableView:heightForRowAtIndexPath:")]
    public nfloat HeightForRow(UITableView tableView, NSIndexPath indexPath)
    
  • Jednotné rozhraní API neposkytuje implicitní převod mezi NSDate a .NET DateTime, protože se nejedná o bezeztrátový převod. Chcete-li zabránit chybám souvisejícím s DateTimeKind.Unspecified převodem rozhraní .NET DateTime na místní nebo UTC před přetypování na NSDate.

  • Objective-C Metody kategorií se teď generují jako rozšiřující metody v sjednoceném rozhraní API. Například kód, který jste dříve použili UIView.DrawString , by teď odkazoval NSString.DrawString na sjednocené rozhraní API.

  • Kód používající třídy AVFoundation s VideoSettings by se měl změnit tak, aby používal vlastnost WeakVideoSettings . To vyžaduje Dictionaryvlastnost , která je k dispozici jako vlastnost u tříd nastavení, například:

    vidrec.WeakVideoSettings = new AVVideoSettings() { ... }.Dictionary;
    
  • Konstruktor NSObject .ctor(IntPtr) byl změněn z veřejného na chráněný (aby se zabránilo nesprávnému použití).

  • NSActionbyla nahrazena standardem .NET Action. Některé jednoduché delegáty (s jedním parametrem) byly také nahrazeny .Action<T>

Nakonec si projděte rozdíly klasického v sjednoceného rozhraní API a vyhledejte změny rozhraní API ve vašem kódu. Hledání na této stránce vám pomůže najít klasická rozhraní API a informace, na které byly aktualizovány.

Poznámka:

Obor MonoTouch.Dialog názvů zůstane po migraci stejný. Pokud váš kód používá MonoTouch.Dialog, měli byste pokračovat v používání tohoto oboru názvů - neměňte MonoTouch.Dialog na !Dialog

Běžné chyby kompilátoru

Další příkladyběžnýchch

Chyba CS0012: Typ MonoTouch.UIKit.UIView je definován v sestavení, na které není odkazováno.

Oprava: Obvykle to znamená, že projekt odkazuje na komponentu nebo balíček NuGet, který nebyl sestaven pomocí sjednoceného rozhraní API. Měli byste odstranit a znovu přidat všechny komponenty a balíčky NuGet. Pokud se tím chyba nevyřeší, nemusí externí knihovna ještě podporovat sjednocené rozhraní API.

Chyba MT0034: Do stejného projektu Xamarin.iOS nelze zahrnout monotouch.dll i Xamarin.iOS.dll – na Xamarin.iOS.dll se odkazuje explicitně, zatímco na monotouch.dll odkazuje Xamarin.Mobile, Version=0.6.3.0, Culture=neutral, PublicKeyToken=null.

Oprava: Odstraňte komponentu, která způsobuje tuto chybu, a znovu přidejte do projektu.

Chyba CS0234: Název typu nebo oboru názvů Foundation v oboru názvů MonoTouch neexistuje. Nechybí odkaz na sestavení?

Oprava: Automatizovaný nástroj pro migraci v Visual Studio pro Mac by měl aktualizovat všechny MonoTouch.Foundation odkazy na Foundation, ale v některých případech bude nutné je aktualizovat ručně. Podobné chyby se mohou objevit u jiných oborů názvů, které byly dříve obsaženy v MonoTouch, například UIKit.

Chyba CS0266: Typ double nelze implicitně převést na System.float.

Oprava: změňte typ a přetypování na nfloat. K této chybě může dojít také u ostatních typů s 64bitovými ekvivalenty (například nint)

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

Chyba CS0266: Typ CoreGraphics.CGRect nelze implicitně převést na System.Drawing.RectangleF. Existuje explicitní převod (chybí přetypování?)

Oprava: Změňte instance na RectangleFCGRect, SizeF na CGSizea PointF na CGPoint. Obor názvů using System.Drawing; by se měl nahradit using CoreGraphics; (pokud ještě není k dispozici).

chyba CS1502: Nejlepší přetížená metoda pro 'CoreGraphics.CGContext.SetLineDash(System.nfloat, System.nfloat[]) má několik neplatných argumentů.

Oprava: Změna typu pole na nfloat[] a explicitní přetypování Math.PI.

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

Chyba CS0115: WordsTableSource.RowsInSection(UIKit.UITableView, int) je označena jako přepsání, ale nebyla nalezena žádná vhodná metoda k přepsání

Oprava: Změna návratové hodnoty a typů parametrů na nint. K tomu často dochází v přepsání metody, jako jsou ty UITableViewSource, včetně RowsInSection, NumberOfSections, GetHeightForRow, TitleForHeaderatd GetViewForHeader.

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

Chyba CS0508: WordsTableSource.NumberOfSections(UIKit.UITableView)Návratový typ musí být System.nint, aby odpovídal přepsaný člen UIKit.UITableViewSource.NumberOfSections(UIKit.UITableView)

Oprava: Při změně návratového typu na nint, přetypování návratové hodnoty na nint.

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

Chyba CS1061: Typ CoreGraphics.CGPath neobsahuje definici pro AddElipseInRect

Oprava: Oprava pravopisu na AddEllipseInRect. Mezi další změny názvu patří:

  • Změňte "Color.Black" na NSColor.Black.
  • Změňte MapKit AddAnnotation na AddAnnotations.
  • Změňte AVFoundation DataUsingEncoding na Encode.
  • Změňte AVFoundation AVMetadataObject.TypeQRCode na AVMetadataObjectType.QRCode.
  • Změňte AVFoundation Video Nastavení na WeakVideoSettings.
  • Změňte PopViewControllerAnimated na PopViewController.
  • Změňte CoreGraphics CGBitmapContext.SetRGBFillColor na SetFillColor.

Chyba CS0546: Nelze přepsat, protože MapKit.MKAnnotation.Coordinate nemá přepisovatelného přístupového objektu sady (CS0546).

Při vytváření vlastní poznámky podtřídou MKAnnotation pole Souřadnice nemá žádné setter, pouze getter.

Oprava

  • Přidání pole pro sledování souřadnic
  • vrátit toto pole v getter vlastnosti Souřadnice
  • Přepsání metody SetCoordinate a nastavení pole
  • Volání SetCoordinate v ctoru s předaným parametrem souřadnic

Mělo by to vypadat nějak takto:

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);
    }
}