Dicas para atualizar o código para a API unificada

Ao atualizar soluções Xamarin mais antigas para a API unificada, os seguintes erros podem ser encontrados.

NSInvalidArgumentException não pôde localizar erro de storyboard

Há um bug na versão atual do Visual Studio para Mac que pode ocorrer depois de usar a ferramenta de migração automatizada para converter seu projeto para as APIs unificadas. Após a atualização, se você receber uma mensagem de erro no formulário:

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

Você pode fazer o seguinte para resolver esse problema, localize o seguinte arquivo de destino de compilação:

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

Neste arquivo, você precisa encontrar a seguinte declaração de destino:

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

E adicione o DependsOnTargets="_CollectBundleResources" atributo a ele. Dessa forma:

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

Salve o arquivo, reinicie o Visual Studio para Mac e faça uma reconstrução limpa do seu projeto. Uma correção para esse problema deve ser lançada pelo Xamarin em breve.

Dicas Úteis

Depois de usar a ferramenta de migração, você ainda pode obter alguns erros do compilador que exigem intervenção manual. Algumas coisas que talvez precisem ser corrigidas manualmente incluem:

  • Comparar enums pode exigir um (int) elenco.

  • NSDictionary.IntValue agora retorna um nint, há um Int32Value que pode ser usado em vez disso.

  • nfloat e nint os tipos não podem ser marcados const, static readonly nint é uma alternativa razoável.

  • As coisas que costumavam estar diretamente no MonoTouch. namespace agora estão geralmente no ObjCRuntime. namespace (por exemplo: MonoTouch.Constants.Version agora é ObjCRuntime.Constants.Version).

  • O código que serializa objetos pode quebrar ao tentar serializar e nfloat digitarnint. Certifique-se de verificar se o código de serialização funciona conforme o esperado após a migração.

  • Às vezes, a ferramenta automatizada perde código dentro #if #else de diretivas condicionais do compilador. Neste caso, você precisará fazer as correções manualmente (veja os erros comuns abaixo).

  • Os métodos exportados manualmente usando [Export] podem não ser corrigidos automaticamente pela ferramenta de migração, por exemplo, neste trecho de código, você deve atualizar manualmente o tipo de retorno para nfloat:

    [Export("tableView:heightForRowAtIndexPath:")]
    public nfloat HeightForRow(UITableView tableView, NSIndexPath indexPath)
    
  • A API unificada não fornece uma conversão implícita entre NSDate e .NET DateTime porque não é uma conversão sem perdas. Para evitar erros relacionados à DateTimeKind.Unspecified conversão do .NET DateTime em local ou UTC antes da conversão para NSDateo .

  • Objective-C os métodos de categoria agora são gerados como métodos de extensão na API unificada. Por exemplo, o código usado anteriormente UIView.DrawString agora faria referência NSString.DrawString na API unificada.

  • O código usando classes AVFoundation com VideoSettings deve ser alterado para usar a WeakVideoSettings propriedade. Isso requer um Dictionary, que está disponível como uma propriedade nas classes de configurações, por exemplo:

    vidrec.WeakVideoSettings = new AVVideoSettings() { ... }.Dictionary;
    
  • O construtor NSObject .ctor(IntPtr) foi alterado de público para protegido (para evitar o uso indevido).

  • NSActionfoi substituído pelo .NET Actionpadrão. Alguns delegados simples (parâmetro único) também foram substituídos por Action<T>.

Finalmente, consulte as diferenças da API Clássica v Unificada para procurar alterações nas APIs em seu código. Pesquisar nesta página ajudará a encontrar APIs clássicas e para o que elas foram atualizadas.

Observação

O MonoTouch.Dialog namespace permanece o mesmo após a migração. Se o seu código usa MonoTouch.Dialog você deve continuar a usar esse namespace - não altere MonoTouch.Dialog para Dialog!

Erros comuns do compilador

Outros exemplos de erros comuns estão listados abaixo, juntamente com a solução:

Erro CS0012: O tipo 'MonoTouch.UIKit.UIView' é definido em um assembly que não é referenciado.

Correção: Isso geralmente significa que o projeto faz referência a um componente ou pacote NuGet que não foi criado com a API unificada. Você deve excluir e adicionar novamente todos os Componentes e pacotes NuGet. Se isso não corrigir o erro, a biblioteca externa pode ainda não oferecer suporte à API unificada.

Erro MT0034: Não é possível incluir 'monotouch.dll' e 'Xamarin.iOS.dll' no mesmo projeto Xamarin.iOS - 'Xamarin.iOS.dll' é referenciado explicitamente, enquanto 'monotouch.dll' é referenciado por 'Xamarin.Mobile, Version=0.6.3.0, Culture=neutral, PublicKeyToken=null'.

Correção: exclua o componente que está causando esse erro e adicione novamente ao projeto.

Erro CS0234: O tipo ou nome de namespace 'Foundation' não existe no namespace 'MonoTouch'. Você não tem uma referência de assembly?

Correção: A ferramenta de migração automatizada no Visual Studio para Mac deve atualizar todas as MonoTouch.Foundation referências ao Foundation, no entanto, em alguns casos, elas precisarão ser atualizadas manualmente. Erros semelhantes podem aparecer para os outros namespaces anteriormente contidos no MonoTouch, como UIKit.

Erro CS0266: Não é possível converter implicitamente o tipo 'double' para 'System.float'

Correção: altere o tipo e converta para nfloat. Esse erro também pode ocorrer para os outros tipos com equivalentes de 64 bits (como nint, )

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

Erro CS0266: Não é possível converter implicitamente o tipo 'CoreGraphics.CGRect' para 'System.Drawing.RectangleF'. Existe uma conversão explícita (há uma conversão ausente?)

Correção: altere as instâncias para RectangleF , CGRectSizeF para CGSizee PointF para CGPoint. O namespace using System.Drawing; deve ser substituído por using CoreGraphics; (se ainda não estiver presente).

erro CS1502: A melhor correspondência de método sobrecarregado para 'CoreGraphics.CGContext.SetLineDash(System.nfloat, System.nfloat[])' tem alguns argumentos inválidos

Correção: altere o tipo de matriz para nfloat[] e converta Math.PIexplicitamente .

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

Erro CS0115: 'WordsTableSource.RowsInSection(UIKit.UITableView, int)' é marcado como uma substituição, mas nenhum método adequado encontrado para substituir

Correção: altere o valor de retorno e os tipos de parâmetro para nint. Isso geralmente ocorre em substituições de método, como as do , UITableViewSourceincluindo RowsInSection, NumberOfSections, , GetHeightForRow, TitleForHeader, GetViewForHeaderetc.

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

Erro CS0508: WordsTableSource.NumberOfSections(UIKit.UITableView): o tipo de retorno deve ser 'System.nint' para corresponder ao membro substituído UIKit.UITableViewSource.NumberOfSections(UIKit.UITableView)

Correção: Quando o tipo de retorno é alterado para nint, converte o valor de retorno em nint.

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

Erro CS1061: Tipo 'CoreGraphics.CGPath' não contém uma definição para 'AddElipseInRect'

Correção: Ortografia correta para AddEllipseInRect. Outras mudanças de nome incluem:

  • Altere 'Color.Black' para NSColor.Black.
  • Altere MapKit 'AddAnnotation' para AddAnnotations.
  • Altere AVFoundation 'DataUsingEncoding' para Encode.
  • Altere AVFoundation 'AVMetadataObject.TypeQRCode' para AVMetadataObjectType.QRCode.
  • Altere AVFoundation 'VideoSettings' para WeakVideoSettings.
  • Altere PopViewControllerAnimated para PopViewController.
  • Altere CoreGraphics 'CGBitmapContext.SetRGBFillColor' para SetFillColor.

Erro CS0546: não é possível substituir porque 'MapKit.MKAnnotation.Coordinate' não tem um acessador de conjunto substituível (CS0546)

Ao criar uma anotação personalizada subclassificando MKAnnotation, o campo Coordenada não tem setter, apenas um getter.

A correção

  • Adicionar um campo para acompanhar a coordenada
  • retornar este campo no getter da propriedade Coordinate
  • Substitua o método SetCoordinate e defina seu campo
  • Chame SetCoordinate em seu ctor com o parâmetro de coordenadas passadas

Ela deve parecer com o seguinte:

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