Compartilhar 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. 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 dos aplicativos .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. Desse 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.

Para configurar o comportamento do vinculador no Visual Studio:

  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 aparador, às vezes ele remove o código que você pode ter chamado dinamicamente, mesmo indiretamente. Você pode instruir o aparador a preservar os membros anotando-os com o DynamicDependency atributo. Esse 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, o corte removeria Helper MyAssembly ou removeria MyAssembly completamente se não fosse 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 corte, permitindo que outros assemblies sejam cortados. Essa abordagem pode ser útil quando você não pode usar facilmente o DynamicDependency atributo ou não controla o código que está sendo cortado.

Quando ele corta todos os assemblies, você pode dizer ao trimmer para ignorar um assembly definindo um TrimmerRootAssembly item do MSBuild no arquivo de projeto:

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

Observação

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

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

Preservar assemblies, tipos e membros

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

Para excluir um membro do processo de corte ao aparar todos os assemblies, defina o TrimmerRootDescriptor item do MSBuild no arquivo de projeto como 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 de corte para definir quais membros excluir:

<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 do corte.

Quando uma montagem, tipo ou membro é listado no XML, a ação padrão é preservação, o que significa que, independentemente de o aparador 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 uma montagem como segura para corte

Se você tiver uma biblioteca em seu projeto ou for um desenvolvedor de uma biblioteca reutilizável e quiser que o aparador trate seu assembly como aparável, poderá marcar o assembly como seguro para corte adicionando a IsTrimmable propriedade 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. "Pode ser cortado" significa que o assembly é considerado compatível com cortes e não deve haver avisos relacionados a cortes quando o assembly for criado. Quando usados em um aplicativo cortado, os membros não utilizados do assembly serão removidos na saída final.

Definir a propriedade IsTrimmable 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 MSBuild ao arquivo de projeto do assembly.

Observação

Se a propriedade IsTrimmable 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 aparador está ativado, ele remove IL que não é estaticamente acessível. Como resultado, os aplicativos que usam reflexão ou outros padrões que criam dependências dinâmicas podem ser interrompidos. Para avisar sobre esses padrões, ao marcar um assembly como seguro para corte, os autores da biblioteca devem definir a SuppressTrimAnalysisWarnings propriedade 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 da biblioteca, ao marcar um assembly como trim safe, você deve habilitar avisos individuais para todos os assemblies definindo a TrimmerSingleWarn propriedade MSBuild como false:

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

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