Font Descriptor é um objeto UIFontDescriptor no iOS e NSFontDescriptor no macOS que encapsula todos os metadados da fonte: família, tipo, tamanho, espaçamento entre letras, entrelinhas e atributos tipográficos. Em vez de criar uma fonte diretamente via UIFont(name:size:), o desenvolvedor descreve as características desejadas através de um descritor, e o sistema seleciona a melhor correspondência entre as fontes disponíveis. De acordo com a Documentação para Desenvolvedores da Apple, o UIFontDescriptor suporta mais de 20 atributos de fonte e é usado em todos os frameworks de tipografia do iOS — desde UIKit até Core Text e SwiftUI.
Pontos principais
Font Descriptor é um objeto que descreve as características de uma fonte como um conjunto de pares chave-valor, em vez de um arquivo de fonte específico. Em vez de criar uma fonte pelo nome, o desenvolvedor especifica a família, o tipo, o tamanho e os atributos opcionais, e o sistema seleciona a melhor correspondência. Essa abordagem é crítica para a tipografia adaptável: o mesmo descritor pode funcionar em diferentes versões do iOS onde o conjunto de fontes disponíveis varia. De acordo com as Diretrizes de Interface Humana do iOS, a correspondência de fontes via descritores é a maneira recomendada de trabalhar com fontes dinâmicas.
Sem o Font Descriptor, os desenvolvedores teriam que verificar a disponibilidade de cada fonte pelo nome e definir manualmente as opções de fallback. O descritor automatiza esse processo: ele contém uma matriz de compatibilidade de tipos (regular, negrito, itálico, negrito itálico) e, quando uma correspondência exata não é encontrada, retorna a mais próxima disponível. A correspondência do sistema funciona no nível do Core Text e está disponível tanto no iOS quanto no macOS através da API unificada NSFontDescriptor.
Os descritores também são usados para fontes personalizadas — carregadas via Info.plist ou adicionadas manualmente. Se uma fonte está registrada no sistema, seu descritor é criado exatamente da mesma forma que para uma fonte do sistema. Nota multiplataforma: o conceito de descritor também existe no Android através do Typeface.Builder, mas a implementação do iOS via UIFontDescriptor fornece significativamente mais atributos — mais de 20 em comparação com 5 no Android.
UIFontDescriptor contém atributos agrupados em um dicionário fontAttributes do tipo [UIFontDescriptor.AttributeName: Any]. Os atributos-chave incluem a família da fonte, nome, tamanho, traços, matriz de transformação, tamanho óptico e estilo de texto. De acordo com a sessão 227 da WWDC 2019 da Apple, o uso de estilos de texto (Dynamic Type) é obrigatório para aplicativos compatíveis com acessibilidade.
O atributo traits é um dicionário contendo características simbólicas: peso (UIFontWeightTrait), inclinação (UIFontSlantTrait), largura (UIFontWidthTrait) e outros. Esses valores são usados pelo correspondente de fontes para selecionar um tipo. Por exemplo, UIFontWeightTrait com valor 0.0 — tipo regular, 0.3 — negrito. O sistema mapeia automaticamente os valores numéricos para as variantes de fonte disponíveis.
Atributos adicionais incluem featureSettings para recursos OpenType (ligaduras, kerning, proporções numéricas), visibleName para exibição ao usuário, matrix para transformações afins da fonte e cascadeList para listas em cascata de fontes de fallback. A lista completa de atributos cobre praticamente todos os cenários de tipografia no iOS e macOS.
| Atributo | Tipo | Descrição |
|---|---|---|
| UIFontDescriptorFamily | String | Família da fonte (SF Pro, Helvetica Neue) |
| UIFontDescriptorName | String | Nome completo da fonte (HelveticaNeue-Bold) |
| UIFontDescriptorSize | NSNumber | Tamanho da fonte em pontos |
| UIFontDescriptorMatrix | NSValue | Matriz de transformação afim |
| UIFontDescriptorTraits | [String: Any] | Características simbólicas do tipo |
| UIFontDescriptorTextStyle | String | Estilo Dynamic Type (headline, body, caption) |
A principal forma de trabalhar com Font Descriptor no iOS é criar um descritor e depois gerar um UIFont a partir dele. Esta é a abordagem preferida quando você precisa de uma fonte com características específicas sem saber o nome exato. O processo consiste em duas etapas: criar um UIFontDescriptor via um inicializador e chamar o método font(withSize:) no descritor.
import UIKit
// Criar descritor de fonte para a família
let descriptor = UIFontDescriptor.init(
fontAttributes: [
.family: "SF Pro",
.traits: [
.weight: UIFont.Weight.bold
]
]
)
// Gerar UIFont a partir do descritor
let font = descriptor.font(withSize: 17)
Essa abordagem garante que o sistema selecione a melhor correspondência para o tipo negrito do SF Pro no dispositivo atual. Vantagem principal — o código não depende da versão do iOS: no iOS 13, o SF Pro será usado; em versões anteriores, a Helvetica Neue ou a fonte do sistema padrão.
Para criar uma fonte com tamanho dinâmico, use o inicializador com estilo de texto e escala. O Dynamic Type ajusta automaticamente o tamanho conforme as configurações do usuário:
// Descritor Dynamic Type
let bodyDescriptor = UIFontDescriptor
.preferredFontDescriptor(withTextStyle: .body)
// Tornar a fonte negrito
let boldDescriptor = bodyDescriptor.withSymbolicTraits([.traitBold])
// Gerar UIFont preservando o tamanho dinâmico
let boldBodyFont = UIFont(
descriptor: boldDescriptor!,
size: bodyDescriptor.pointSize
)
Importante: o método withSymbolicTraits retorna um descritor opcional — se o tipo solicitado não estiver disponível, ele retorna nil. Sempre verifique o opcional antes de usar.
O Font Descriptor suporta um modelo imutável — cada método de modificação retorna um novo descritor com o atributo alterado. Isso segue a semântica de valor e torna o código previsível: o descritor original nunca muda. Os principais métodos de modificação são: addingAttributes para adicionar atributos, withFace para alterar o tipo, withSize para alterar o tamanho e withMatrix para transformação afim.
O método addingAttributes é o mais flexível. Ele recebe um dicionário de atributos e retorna um novo descritor. Quando as chaves coincidem, novos valores substituem os antigos. Isso permite combinar alterações: adicionar peso, alterar o tamanho e ativar ligaduras em uma única chamada. De acordo com a Pergunta Técnica QA1682 da Apple, o addingAttributes é a maneira recomendada para modificação em massa via extensão.
Caso de uso prático: criar uma fonte para texto monoespaçado em um editor de código. O desenvolvedor pega o descritor monoespaçado do sistema, adiciona um peso reduzido para linhas finas e aumenta o espaçamento entre letras via featureSettings. Isso fornece código mais legível sem carregar uma fonte separada.
let monoDescriptor = UIFontDescriptor.monospacedDigitFontDescriptor()
// Adicionar atributos personalizados
let customDescriptor = monoDescriptor.addingAttributes([
.size: 14,
.traits: [
.weight: UIFont.Weight.medium
]
])
let monoFont = UIFont(
descriptor: customDescriptor,
size: 14
)
Limitação: nem todos os atributos podem ser alterados após criar o descritor. Por exemplo, a família da fonte é definida uma vez durante a inicialização. Se você precisar alterar a família, crie um novo descritor. Isso está relacionado à arquitetura do Core Text, onde o descritor está vinculado a um recurso de fonte específico.
A correspondência de fontes é um recurso-chave do Font Descriptor que seleciona automaticamente a melhor correspondência para os atributos solicitados entre as fontes instaladas. O processo inclui três etapas: filtragem (exclusão de fontes incompatíveis), classificação (ordenação por grau de correspondência) e seleção (retorno do melhor resultado). A correspondência é executada no nível do Core Text — o framework subjacente a toda tipografia do iOS.
Para encontrar todas as fontes que correspondem a um descritor, use o método matchingFontDescriptors. Ele retorna um array de descritores ordenados por relevância. O desenvolvedor pode selecionar a correspondência exata (primeiro elemento) ou percorrer as opções para lógica personalizada. De acordo com o Guia de Manipulação de Fontes da Apple, esta é a única maneira de obter uma lista de tipos disponíveis para uma família específica sem enumerar pelo nome.
Caso de uso: ao selecionar uma fonte em uma interface de configuração de texto. O usuário escolhe uma família e o aplicativo usa matchingFontDescriptors para obter todos os tipos disponíveis e exibi-los em um seletor. Sem a correspondência, os desenvolvedores teriam que codificar uma lista de opções que muda entre versões do iOS.
let searchDescriptor = UIFontDescriptor.init(
fontAttributes: [.family: "SF Mono"]
)
// Obter todos os tipos disponíveis
let matchingDescriptors = searchDescriptor
.matchingFontDescriptors(withMandatoryKeys: nil)
for descriptor in matchingDescriptors {
print(descriptor.object(forKey: .visibleName) ?? "unnamed")
}
Chaves obrigatórias — um parâmetro que restringe a pesquisa. Se você especificar [.family], a correspondência retorna todas as fontes da família especificada. Se você especificar [.family, .traits] — apenas aquelas que correspondem tanto à família quanto ao tipo. O uso de chaves obrigatórias acelera a correspondência ao pesquisar um subconjunto de fontes.
Desempenho: a correspondência é uma operação síncrona que leva de 0,5 a 5 ms no iOS. Para uma única pesquisa, isso é insignificante, mas para iteração em massa sobre descritores (por exemplo, em um seletor com mais de 50 fontes), recomenda-se armazenar os resultados em cache. A Apple recomenda realizar a correspondência uma vez ao carregar a tela e salvar o array de descritores.
Core Text é um framework de baixo nível baseado em C para trabalhar com tipografia no iOS e macOS. Sua contraparte do UIFontDescriptor é o CTFontDescriptor, que fornece as mesmas capacidades no nível do Core Foundation. O CTFontDescriptor é usado nas APIs do Core Text para criar fontes, medir texto e renderizar tipografia complexa. O UIFontDescriptor é essencialmente um wrapper Objective-C em torno do CTFontDescriptor com um conjunto estendido de atributos.
A ponte toll-free entre UIFontDescriptor e CTFontDescriptor permite passar descritores entre UIKit e Core Text sem conversão. Isso é crítico para aplicativos que usam renderização de texto personalizada — por exemplo, editores de texto baseados em TextKit ou editores de código com realce de sintaxe. Exemplo: CTFontDescriptorCreateCopyWithAttribute cria uma cópia do descritor com um atributo adicionado — um análogo do addingAttributes do UIFontDescriptor.
O atributo-chave kCTFontURLAttribute no CTFontDescriptor contém a URL do arquivo da fonte. Isso permite determinar se uma fonte é do sistema ou personalizada. Para fontes personalizadas, a URL aponta para o arquivo da fonte (.ttf ou .otf); para fontes do sistema, aponta para o diretório de fontes do sistema. Os dados através do descritor são somente leitura; a modificação do arquivo da fonte via URL não é suportada.
Para tipografia avançada — ligaduras personalizadas, substituições contextuais, glifos alternativos — use CTFontDescriptorCopyAttribute com a chave kCTFontFeatureSettingsAttribute. Este atributo contém um array de dicionários de recursos OpenType que podem ser adicionados através do descritor. De acordo com o Guia de Programação do Core Text da Apple, combinar UIFontDescriptor com Core Text fornece controle total sobre a tipografia do aplicativo.
Perguntas frequentes
UIFont é uma fonte pronta para uso que renderiza texto. O Font Descriptor é uma descrição de fonte — um conjunto de atributos a partir do qual um UIFont pode ser criado. Um único descritor pode produzir múltiplos UIFonts de tamanhos diferentes.
Sim. Se a fonte estiver registrada no sistema (via Info.plist ou Core Graphics), seu descritor é criado por família ou por nome exatamente da mesma forma que para fontes do sistema. A correspondência funciona para qualquer fonte registrada.
Use descriptor.object(forKey: .visibleName) para obter o nome exibido, ou descriptor.postscriptName para o nome PostScript. O nome PostScript é usado ao criar uma fonte através de UIFont(name:size:).
Uma lista em cascata é um array de descritores aninhados que servem como fontes de fallback. Se a fonte principal não contiver um caractere necessário, o sistema verifica sequencialmente as fontes da lista em cascata. É usado para suporte a emojis e caracteres CJK.
Sim. O SwiftUI suporta Font Descriptor através de Font(descriptor:size:). O wrapper do SwiftUI aceita um UIFontDescriptor e cria uma fonte SwiftUI, preservando todos os atributos do descritor — kerning, ligaduras e tipo.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também