Partilhar via


Vincular um aplicativo do .NET MAUI para iOS

Ao criar o seu aplicativo, a .NET Multi-Platform App UI (.NET MAUI) pode usar um vinculador chamado ILLink para reduzir o tamanho geral do aplicativo. ILLink reduz o tamanho analisando o código intermediário produzido pelo compilador. Ele remove métodos, propriedades, campos, eventos, structs e classes não utilizados para produzir um aplicativo que contém apenas dependências de código e assembly necessárias para executar o aplicativo.

Comportamento do vinculador

O vinculador dá suporte a três modos para aplicativos do .NET MAUI no iOS e no Mac Catalyst:

  • Não vincule. Desabilitar a vinculação garante que os assemblies não sejam modificados.
  • Vincule somente assemblies do SDK. Deste modo, o vinculador deixa seus assemblies intocados e reduz o tamanho dos assemblies do SDK removendo tipos e membros que o seu aplicativo não usa.
  • Vincule todos os assemblies. Quando ele vincula todos os assemblies, o vinculador executa otimizações adicionais para tornar o seu aplicativo o menor possível. Ele modifica o código intermediário do código-fonte, que pode interromper seu aplicativo se você usar recursos usando uma abordagem que a análise estática do vinculador não pode detectar. Nesses casos, talvez seja necessário fazer ajustes no código-fonte para fazer o seu aplicativo funcionar corretamente.

O comportamento do vinculador pode ser configurado para cada configuração de build do seu aplicativo.

Aviso

Habilitar o vinculador para a configuração de depuração do aplicativo pode dificultar sua experiência de depuração, pois pode remover acessadores de propriedade que permitem inspecionar o estado de seus objetos.

  1. No Gerenciador de Soluções, clique com o botão direito do mouse em seu projeto de aplicativo do .NET MAUI e selecione Propriedades. Em seguida, navegue até a guia iOS > Build e defina a lista suspensa de Comportamento do vinculador para o comportamento desejado do vinculador:

    Captura de tela do comportamento do vinculador para iOS no Visual Studio.

Preservar código

Quando você usa o vinculador, ele às vezes remove o código que você pode ter chamado dinamicamente, mesmo indiretamente. Você pode instruir o vinculador a preservar os membros anotando-os com o atributo DynamicDependency. Este atributo pode ser usado para expressar uma dependência em um tipo e subconjunto de membros ou em membros específicos.

Importante

Todos os membros do BCL que não podem ser determinados estaticamente para serem usados pelo aplicativo estão sujeitos a serem removidos.

O atributo DynamicDependency pode ser aplicado a construtores, campos e métodos:

[DynamicDependency("Helper", "MyType", "MyAssembly")]
static void RunHelper()
{
    var helper = Assembly.Load("MyAssembly").GetType("MyType").GetMethod("Helper");
    helper.Invoke(null, null);
}

Neste exemplo, DynamicDependency garante que o método Helper seja mantido. Sem o atributo, a vinculação removeria Helper de MyAssembly ou removeria MyAssembly completamente se não referenciado em outro lugar.

O atributo especifica o membro a ser mantido por meio de um string ou por meio do atributo DynamicallyAccessedMembers. O tipo e o assembly são implícitos no contexto do atributo ou explicitamente especificados no atributo (por Type, ou por strings para o tipo e nome do assembly).

As cadeias de caracteres de tipo e membro usam uma variação do formato de cadeia de caracteres de ID de comentário da documentação C#, sem o prefixo do membro. A cadeia de caracteres de membro não deve incluir o nome do tipo declarativo e pode omitir parâmetros para manter todos os membros do nome especificado. Os exemplos a seguir mostram usos válidos:

[DynamicDependency("Method()")]
[DynamicDependency("Method(System,Boolean,System.String)")]
[DynamicDependency("MethodOnDifferentType()", typeof(ContainingType))]
[DynamicDependency("MemberName")]
[DynamicDependency("MemberOnUnreferencedAssembly", "ContainingType", "UnreferencedAssembly")]
[DynamicDependency("MemberName", "Namespace.ContainingType.NestedType", "Assembly")]
// generics
[DynamicDependency("GenericMethodName``1")]
[DynamicDependency("GenericMethod``2(``0,``1)")]
[DynamicDependency("MethodWithGenericParameterTypes(System.Collections.Generic.List{System.String})")]
[DynamicDependency("MethodOnGenericType(`0)", "GenericType`1", "UnreferencedAssembly")]
[DynamicDependency("MethodOnGenericType(`0)", typeof(GenericType<>))]

Preservar assemblies

É possível especificar assemblies que devem ser excluídos do processo de vinculação, permitindo que outros assemblies sejam vinculados. Esta abordagem pode ser útil quando você não pode usar facilmente o atributo DynamicDependency ou não controlar o código que está sendo vinculado.

Quando ele vincula todos os assemblies, você pode dizer ao vinculador para ignorar um assembly definindo a propriedade TrimmerRootAssembly do MSBuild em uma marca <ItemGroup> no arquivo de projeto:

<ItemGroup>
  <TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>

Observação

A extensão .dll não é necessária ao definir a propriedade TrimmerRootAssembly do MSBuild.

Se o vinculador ignorar um assembly, ele será considerado enraizado, o que significa que ele e todas as suas dependências estaticamente compreendidas serão mantidas. Você pode ignorar assemblies adicionais adicionando mais propriedades TrimmerRootAssembly do MSBuild ao <ItemGroup>.

Preservar assemblies, tipos e membros

Você pode passar ao vinculador um arquivo de descrição XML que especifica quais assemblies, tipos e membros precisam ser mantidos.

Para excluir um membro do processo de vinculação ao vincular todos os assemblies, defina a propriedade TrimmerRootDescriptor do MSBuild em uma marca <ItemGroup> no arquivo de projeto para o arquivo XML que define os membros a serem excluídos:

<ItemGroup>
  <TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>

Em seguida, o arquivo XML usa o formato de descritor do aparador para definir quais membros excluir da vinculação:

<linker>
  <assembly fullname="MyAssembly">
    <type fullname="MyAssembly.MyClass">
      <method name="DynamicallyAccessedMethod" />
    </type>
  </assembly>
</linker>

Neste exemplo, o arquivo XML especifica um método que é acessado dinamicamente pelo aplicativo, que é excluído da vinculação.

Quando um assembly, tipo ou membro é listado no XML, a ação padrão é a preservação, o que significa que, independentemente de o vinculador achar que é usado ou não, ele é preservado na saída.

Observação

As marcas de preservação são ambíguas inclusivas. Se você não fornecer o próximo nível de detalhes, ele incluirá todos os filhos. Se um assembly estiver listado sem nenhum tipo, todos os tipos e membros do assembly serão preservados.

Marcar um assembly como seguro para o vinculador

Se você tiver uma biblioteca em seu projeto ou for um desenvolvedor de uma biblioteca reutilizável e quiser que o vinculador trate o seu assembly como vinculável, você pode marcar o assembly como seguro para o vinculador adicionando a propriedade IsTrimmable do MSBuild ao arquivo de projeto do assembly:

<PropertyGroup>
    <IsTrimmable>true</IsTrimmable>
</PropertyGroup>

Isso marca o assembly como "pode ser cortado" e habilita os avisos de corte para o respectivo projeto. Ser "pode ser cortado" significa que o assembly é considerado compatível com cortes e não deve haver avisos relacionados a cortes quando o assembly é criado. Quando usados em um aplicativo cortado, os membros não utilizados do assembly são removidos na saída final.

Definir a propriedade IsTrimmable do MSBuild como true no arquivo de projeto insere o atributo AssemblyMetadata no assembly:

[assembly: AssemblyMetadata("IsTrimmable", "True")]

Como alternativa, você pode adicionar o atributo AssemblyMetadata ao assembly sem ter adicionado a propriedade IsTrimmable do MSBuild ao arquivo de projeto do assembly.

Observação

Se a propriedade IsTrimmable do MSBuild estiver definida para um assembly, isso substituirá o atributo AssemblyMetadata("IsTrimmable", "True"). Isso permite que você opte pelo corte em um assembly mesmo que ele não tenha o atributo ou desabilite o corte de um assembly que tenha o atributo.

Suprimir avisos de análise

Quando o vinculador está habilitado, ele remove IL que não é estaticamente acessível. Os aplicativos que usam reflexão ou outros padrões que criam dependências dinâmicas podem ser interrompidos como resultado. Para alertar sobre esses padrões, ao marcar um assembly como seguro para o vinculador, os autores da biblioteca devem definir a propriedade SuppressTrimAnalysisWarnings do MSBuild como false:

<PropertyGroup>
  <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
</PropertyGroup>

Não suprimir avisos de análise de corte incluirá avisos sobre todo o aplicativo, incluindo seu próprio código, código de biblioteca e código SDK.

Mostrar avisos detalhados

A análise de corte produz no máximo um aviso para cada assembly proveniente de um PackageReference, indicando que os internos do assembly não são compatíveis com cortes. Como autor de biblioteca, ao marcar um assembly como seguro para o vinculador, você deve habilitar avisos individuais para todos os assemblies definindo a propriedade TrimmerSingleWarn do MSBuild como false:

<PropertyGroup>
  <TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>

Esta configuração mostra todos os avisos detalhados, em vez de recolhê-los em um único aviso por assembly.

Confira também