← Todos os Posts

Liquid Glass no SwiftUI: Três padrões aprendidos ao publicar Return no iOS 26

O Liquid Glass da Apple é uma API SwiftUI de uma única linha: .glassEffect().1 O Return, meu timer de meditação, usa o efeito nove vezes em iOS, macOS e tvOS.2 Um desses usos aplica o modificador a um Shape customizado que transforma os próprios números do timer em liquid glass, glifo por glifo.

Return no iPhone exibindo os números do timer em Liquid Glass refratando o background do tema fogo, com o seletor de duração em HUD de glass logo abaixo

A pergunta interessante é o que acontece quando você vai além do one-liner. As Human Interface Guidelines da Apple definem uma regra rígida de camadas: o Liquid Glass pertence à camada funcional (controles, navegação, UI transitória) e nunca à camada de conteúdo.3 A maioria dos nove usos no Return são aplicações de manual da camada funcional: pickers, botões, faixas de controles, badges de estado pausado. Os usos interessantes são os três que dobram as regras sem quebrá-las.

Este ensaio percorre três padrões que publiquei, as regras que respeitam, as armadilhas que me pegaram e a superfície da API que decidi deliberadamente não usar.

TL;DR

  • O iOS 26 traz o Liquid Glass como .glassEffect(_:in:). A variante padrão é .regular e o shape padrão é Capsule.1
  • O Return usa três padrões que vão além do one-liner: glass em um Shape customizado (texto do timer via paths de glifos do Core Text), o padrão de espelho (reflexo abaixo via cópia invertida e mascarada) e overlays de HUD na camada funcional.
  • Regra do HIG da Apple: Liquid Glass para a camada funcional, materiais padrão para a camada de conteúdo.3
  • Decidi deliberadamente não usar GlassEffectContainer. A API de morphing não tem caso de uso no Return (nenhum elemento de glass anima até virar outro), e eu não fiz benchmarks da diferença de performance de renderização; é um trade-off não medido, não uma recomendação.1
  • Armadilhas: glass sobre fundo plano parece plano; renderização de dígitos sem jitter exige células de largura fixa; o HStack no tvOS ignora o valor do environment de direção de layout; reduce-motion precisa ser respeitado na animação de morph.

A API de uma linha e a regra de camadas

A Apple lançou o Liquid Glass com uma superfície pequena, apresentada como um pilar de design importante na WWDC 2025:113

Text("Hello, World!")
    .font(.title)
    .padding()
    .glassEffect()                              // default: .regular variant, Capsule shape

Text("Hello, World!")
    .glassEffect(in: .rect(cornerRadius: 16))   // custom shape

Text("Hello, World!")
    .glassEffect(.regular.tint(.orange).interactive())  // tint + touch reactivity

Três botões: variante (.regular ou .clear), shape (qualquer Shape) e uma cadeia GlassEffectStyle (tint, interactive). Essa é a API inteira para uma única view. Renderização multi-view é tratada por um GlassEffectContainer separado, ao qual chegarei.

O HIG é mais restrito do que a API. As Human Interface Guidelines da Apple definem duas camadas em toda interface no iOS 26+:3

  1. A camada de conteúdo: o documento, lista, foto ou mídia que a pessoa está consumindo. Use materiais padrão aqui (os já existentes .regularMaterial, .thinMaterial etc.).
  2. A camada funcional: controles, navegação, tab bars, sidebars, overlays transitórios. Use Liquid Glass aqui.

A instrução específica da Apple: “Don’t use Liquid Glass in the content layer. Liquid Glass works best when it provides a clear distinction between interactive elements and content, and including it in the content layer can result in unnecessary complexity and a confusing visual hierarchy.”3

A regra parece restritiva até você mapeá-la em um app real. O Return é um timer de meditação. Sua camada de conteúdo é a imagem de respiração e o vídeo em loop que roda atrás de tudo. Sua camada funcional é o seletor de duração, a pilha de botões iniciar/pausar/parar, a linha de botões secundários de configurações e (no tvOS) o badge de estado pausado. Oito dos nove usos de glass no Return são aplicações de manual da camada funcional: três variantes do seletor de duração para os caminhos de código do iOS e macOS, o toggle iniciar/pausar, o botão parar, a linha do botão de configurações, o indicador de pausado do tvOS e mais um overlay transitório de controle.4

O nono é o caso-limite deliberado (Liquid Glass nos próprios números do timer), que a próxima seção percorre.

Padrão 1: Glass em um Shape customizado

Os números do timer no Return não são texto desenhado sobre um background de glass. O glass é o texto. .glassEffect(.clear, in:) aceita qualquer Shape,9 e um Shape é um protocolo produtor de Path.10 Então o truque é: converter a string do timer em um path de glifos usando Core Text,11 e passar esse path-como-Shape para .glassEffect.56

import SwiftUI
@preconcurrency import CoreText

struct GlassTextShape: Shape {
    let text: String
    let font: CTFont

    func path(in rect: CGRect) -> Path {
        guard !text.isEmpty else { return Path() }
        let combinedPath = CGMutablePath()

        let attrString = NSAttributedString(string: text, attributes: [.font: font])
        let line = CTLineCreateWithAttributedString(attrString)
        guard let runs = CTLineGetGlyphRuns(line) as? [CTRun], !runs.isEmpty else {
            return Path()
        }

        for run in runs {
            let glyphCount = CTRunGetGlyphCount(run)
            guard glyphCount > 0 else { continue }
            var glyphs = [CGGlyph](repeating: 0, count: glyphCount)
            var positions = [CGPoint](repeating: .zero, count: glyphCount)
            let range = CFRange(location: 0, length: glyphCount)
            CTRunGetGlyphs(run, range, &glyphs)
            CTRunGetPositions(run, range, &positions)

            for i in 0..<glyphCount {
                guard let glyphPath = CTFontCreatePathForGlyph(font, glyphs[i], nil) else { continue }
                let transform = CGAffineTransform(translationX: positions[i].x, y: positions[i].y)
                combinedPath.addPath(glyphPath, transform: transform)
            }
        }

        // Core Text y-axis is flipped vs SwiftUI; flip then re-bound and center.
        var swiftPath = Path(combinedPath).applying(CGAffineTransform(scaleX: 1, y: -1))
        let flippedBounds = swiftPath.boundingRect
        let offsetX = rect.midX - flippedBounds.midX
        let offsetY = rect.midY - flippedBounds.midY
        return swiftPath.applying(CGAffineTransform(translationX: offsetX, y: offsetY))
    }
}

Código real de produção em Return/Return/GlassTextShape.swift.5 A função path(in:) usa Core Text para fazer o layout da string, percorre cada CTRun, extrai o CGPath de cada glifo e os une em um único CGMutablePath. Os dois passos não óbvios vêm depois da união: o sistema de coordenadas do Core Text coloca a origem no canto inferior esquerdo, enquanto o Path do SwiftUI a coloca no canto superior esquerdo, então o path precisa ser invertido via CGAffineTransform(scaleX: 1, y: -1). Em seguida, o boundingRect do path invertido tem valores y negativos, então uma translação o recentra dentro do rect que o SwiftUI passa para o Shape. Pule qualquer uma das transformações e os glifos renderizam de cabeça para baixo ou fora da tela.

A aplicação é uma única linha:

Rectangle()
    .fill(.clear)
    .glassEffect(.clear, in: textShape)
    .frame(width: cellWidth, height: cellHeight)

O Rectangle transparente é um placeholder de hit-target; o visual real é qualquer shape que textShape produzir. Com um shape baseado em path de glifo, o material Liquid Glass preenche apenas os contornos dos glifos. O resultado: cada dígito do timer é uma forma separada de liquid glass, refratando qualquer animação que rode atrás dele.6

A nuance do HIG. A regra declarada pela Apple é Liquid Glass para a camada funcional, materiais padrão para a camada de conteúdo, com uma exceção explícita: controles interativos transitórios na camada de conteúdo (sliders, toggles) podem usar Liquid Glass quando ativados.3 Os números do timer no Return são exibição de estado, não um controle: eles atualizam uma vez por segundo a partir de Timer.publish(every: 1, ...) e não têm gesto de toque (o botão iniciar/pausar abaixo deles é o que alterna o estado). Então colocar Liquid Glass neles é um caso-limite deliberado, mais próximo de “controle interativo transitório” por intenção do que por interatividade literal, já que os números são o ponto focal visual que o usuário observa durante toda a sessão. Estou dobrando a regra, não quebrando. Um revisor que lesse o HIG ao pé da letra poderia argumentar que isso deveria ser material padrão; eu argumento que o timer é uma superfície de controle de tempo decorrido na mesma família de um indicador de progresso. A documentação da Apple não julga o caso diretamente.

Por que Shape customizado em vez de Text + background. Text renderizado acima de um background de glass parece texto sobre glass. Text renderizado como o próprio glass parece uma categoria visual diferente. O usuário percebe os números como foreground funcional, especificamente como um elemento transitório que existe para ser olhado através, não para.

Padrão 2: O padrão do espelho

O Return mostra um reflexo do timer abaixo dele, com fade out. Código real de produção:6

Return no Mac mostrando o seletor de duração como overlay HUD em Liquid Glass, com o tratamento glass do texto do timer visível acima

VStack(spacing: 0) {
    GlassTimerText(text: displayTime, fontSize: fontSize)
        .accessibilityLabel("Time remaining: \(accessibleDescription)")

    if showReflection {
        GlassTimerText(text: displayTime, fontSize: fontSize)
            .scaleEffect(x: 1, y: -1)
            .mask(
                LinearGradient(
                    stops: [
                        .init(color: .white.opacity(0.2), location: 0),
                        .init(color: .clear, location: 0.6)
                    ],
                    startPoint: .top,
                    endPoint: .bottom
                )
            )
            .offset(y: -8)
            .accessibilityHidden(true)
    }
}

Três transformações compõem o espelho, todas primitivas padrão do SwiftUI:14

  1. scaleEffect(x: 1, y: -1) inverte a segunda cópia de cabeça para baixo.
  2. .mask(LinearGradient(...)) faz o reflexo desbotar de 20% de opacidade no topo até totalmente transparente a 60% para baixo.
  3. .offset(y: -8) puxa o reflexo 8 pontos para cima para que ele encoste no original em vez de deixar uma emenda visível.

O modificador .accessibilityHidden(true) no reflexo é estrutural. O VoiceOver não deve anunciar o tempo espelhado duas vezes; o accessibilityLabel e o accessibilityAddTraits(.updatesFrequently) do original já estão anexados à instância principal de GlassTimerText acima, e o reflexo é puramente decorativo.

Por que isso funciona especificamente com Liquid Glass. O reflexo herda o material glass de GlassTimerText. Qualquer fundo sobre o qual o original esteja (um gradiente de círculo de respiração, um vídeo, uma cena tonalizada) refrata através de ambas as cópias. O espelho não precisa de nenhum código específico de glass; o material glass cuida da refração de graça. O efeito inteiro são três modificadores e um gradiente.

O custo de acessibilidade. Usuários de reduce-motion ainda veem o espelho, mas a animação do material glass entre atualizações de tempo é suprimida em outros lugares via @Environment(\.accessibilityReduceMotion).7 O reflexo em si é estático; apenas o morph entre transições de dígitos é animado.

Padrão 3: Overlays de HUD em Glass para controles transitórios

Os oito usos restantes de glass no Return são aplicações de manual da camada funcional.4 Cada um segue o mesmo padrão:

Return no Apple Watch mostrando Liquid Glass na camada funcional sobre o controle iniciar/pausar em tamanho de canvas pequeno

durationPicker
    .frame(height: 50)
    .frame(maxWidth: 320)
    .glassEffect()
    .padding(.horizontal, 20)
    .transition(.opacity.combined(with: .scale(scale: 0.95)))

O .transition(.opacity.combined(with: .scale(scale: 0.95))) é a parte estrutural. Liquid Glass em controles transitórios só fica certo quando os controles transitam. Um HUD de glass estático que fica permanentemente na tela parece chrome. Um HUD de glass que faz fade+scale na entrada quando o usuário toca e na saída quando ele desvia o olhar parece uma superfície de controle momentânea.

A documentação da Apple sobre glassEffect observa isso implicitamente: o modificador “captures the content to send to the container to render” e “react[s] to touch and pointer interactions in real time.”1 Os hooks de animação não estão na API, mas o pipeline de renderização presume que elementos glass se movem. Elementos glass estáticos perdem essa affordance.

O Return usa o padrão para o seletor de duração (sobe quando o usuário toca), o botão toggle iniciar/pausar (sempre visível, mas com scale ao pressionar), o botão parar (visível apenas no meio da sessão), a linha do botão de configurações (uma faixa horizontal de controles abaixo do seletor de duração) e o badge de estado pausado do tvOS (visível apenas quando uma sessão está pausada na Apple TV). Todos os cinco contextos respeitam a regra de camada funcional do HIG.3

Return na Apple TV mostrando o tratamento Liquid Glass dimensionado para uma interface de 10 pés

A questão do GlassEffectContainer

A Apple recomenda GlassEffectContainer sempre que um app usa .glassEffect() em múltiplas views, por dois motivos: melhor performance de renderização (efeitos de glass são agrupados em batch) e a habilidade de fazer morph de shapes uns nos outros durante transições.1

Eu não usei. O raciocínio é específico da aplicação, não uma refutação da orientação da Apple. O Return tem nove views de glass, nenhuma das quais precisa fazer morph entre si.46 O seletor de duração nunca anima até virar o botão iniciar. O texto do timer nunca anima até virar a linha do botão de configurações. Cada elemento glass é independente. A API de morphing não teria caso de uso para disparar, e as regras de espaçamento do container restringiriam layouts que hoje não precisam de coordenação.

O argumento de performance de renderização eu não posso refutar totalmente sem medição. A documentação da Apple alerta que “too many” efeitos glass fora de um container podem degradar a performance.1 As nove views do Return nunca compartilham a tela ao mesmo tempo (o seletor de duração só aparece no estado de menu, o botão parar só quando pausado no meio da sessão). Em qualquer frame dado, conto três ou quatro elementos glass visíveis, o que tem rodado fluido em todos os dispositivos que testei em iOS, iPadOS, macOS, watchOS e tvOS, mas não rodei um trace do Instruments comparando container-wrapped contra modifier-only. Então a leitura honesta: o Return pula GlassEffectContainer baseado em uma experiência de usuário observada como boa, não em uma equivalência de performance medida.

A regra que tirei disso: GlassEffectContainer é para apps onde múltiplos elementos glass estão visíveis e animando simultaneamente. O exemplo da Apple é renderização de conjuntos de símbolos com glassEffectUnion(id:namespace:): quatro símbolos de clima que se fundem e se separam fluidamente como uma unidade.1 Esse é um caso de uso de manual. Se um recurso futuro do Return precisar que elementos glass façam morph ou compartilhem regras de espaçamento de um container, o container é a ferramenta certa para adicionar nessa hora. Para o app de hoje, ainda não bati no caso.

As armadilhas que me pegaram

Três bugs reais de produção:

Jitter dos dígitos em glass. A SF Pro Rounded tem dígitos de largura variável em renderização proporcional. Conforme o timer contava, a string exibida mudava de comprimento, e o HStack ao redor refluía a cada segundo, fazendo o timer inteiro tremer. A correção: células de largura fixa para cada caractere. Cada dígito ganha um cellWidth de fontSize * 0.6, cada dois-pontos ganha fontSize * 0.3, e o HStack se torna uma grade estável.6

HStack(spacing: 0) {
    ForEach(Array(text.enumerated()), id: \.offset) { _, char in
        let isColon = char == ":"
        let cellWidth = isColon ? colonCellWidth : digitCellWidth
        GlassDigitCell(character: String(char), font: ctFont,
                       cellWidth: cellWidth, cellHeight: cellHeight)
    }
}

As células não são padrão Apple; são um workaround para renderização de largura proporcional em tamanhos de fonte fixos pequenos. A SF Pro Rounded da Apple com .monospacedDigit() resolveria o mesmo problema em Text, mas o modificador não está disponível em um renderizador de glass baseado em Shape customizado. O layout de células fixas é o substituto.

Override de direção de layout no tvOS. O mesmo GlassTimerText rodava em iOS, iPadOS, macOS e tvOS. No tvOS especificamente, o HStack espelhava sob um environment de idioma Right-to-Left, mesmo que a versão iOS respeitasse o override no environment. A correção: fixar a direção de layout tanto via valor do environment quanto via o modificador explícito flipsForRightToLeftLayoutDirection(false), aplicado diretamente ao HStack de células de dígitos (o VStack pai aplica separadamente o override do environment para que a cópia do reflexo o herde):6

HStack(spacing: 0) { ... }
    .flipsForRightToLeftLayoutDirection(false)
    .environment(\.layoutDirection, .leftToRight)

A razão: o HStack do tvOS parece ignorar o override em nível de environment em algumas versões, e flipsForRightToLeftLayoutDirection(false) é o contrato explícito de não-espelhar que é honrado de forma mais confiável.12 Cinto e suspensórios.

Reduce-motion no morph dos dígitos. O Liquid Glass anima transições de morph entre strings exibidas por padrão. Usuários com accessibilityReduceMotion ativado viam o morph como flickering. A correção:6

.animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: displayTime)

O modificador de animação lê @Environment(\.accessibilityReduceMotion) e desabilita a transição inteiramente quando reduce-motion está ligado. A orientação de acessibilidade da Apple é explícita: qualquer animação decorativa deve respeitar a preferência de movimento do usuário.7

Quando não usar Liquid Glass

A recusa faz parte do design.

Não coloque Liquid Glass na camada de conteúdo. O HIG da Apple é explícito, e ignorar a regra produz uma hierarquia confusa: o usuário não consegue dizer o que é interativo e o que é conteúdo.3 Se um efeito glass está decorando uma linha de lista ou um card de foto, o design está brigando com a plataforma.

Não use glass sobre fundo plano. O Liquid Glass refrata o que está atrás dele. Se “o que está atrás dele” é uma única cor sólida, a refração não tem nada para curvar, e o resultado parece um retângulo plano tonalizado. Ou coloque glass sobre conteúdo variado (um gradiente, uma imagem, um vídeo) ou não use glass de jeito nenhum. A tela do timer no Return roda imagens de capa baseadas em tema e vídeo em loop como background através de VideoBackgroundView,4 especificamente para que os elementos glass acima dela sempre tenham textura para refratar.

Tenha cautela com glass sobre conteúdo de alta frequência. A renderização do material glass é limitada por GPU, e a animação de morph padrão entre mudanças de shape do glass é em si uma animação. Um timer que atualiza uma vez por segundo está bem nos meus testes; uma waveform ou um visualizador de áudio a 60 Hz não está comprovado e provavelmente briga com a animação de morph. Não fiz benchmark do limite superior; trate isto como heurística, não como threshold medido. A documentação da Apple não publica nenhum.

Não publique glass sem testar reduce-motion. Toda animação de glass deve estar condicionada a accessibilityReduceMotion.7 O morph padrão entre shapes glass é um efeito cinético, não apenas um fade.

O que o Liquid Glass significa para apps que rodam no iOS 26+

A tese é pequena. O Liquid Glass é uma API de uma única linha apenas quando o app já respeita a regra de camadas do HIG. Um app SwiftUI que coloca controles na camada funcional e conteúdo na camada de conteúdo pode adotar o Liquid Glass com modificadores .glassEffect() e parecer nativo por padrão.

Apps que misturam as duas camadas (controles dentro de linhas de lista, barras de navegação tratadas como conteúdo, chrome decorativo em cards de foto) vão adotar o Liquid Glass e parecer errados. O material está correto; a arquitetura por baixo dele não está.

O padrão de Shape customizado (Padrão 1) estende a regra de forma limpa. Qualquer coisa que seja funcionalmente um controle pode usar Liquid Glass, mesmo que não pareça um “controle” no sentido convencional. Um timer é um controle, um medidor de nível é um controle, um indicador de progresso é um controle. Liquid Glass em qualquer um deles está dentro da spec.

Combine este post com meus textos anteriores sobre publicar a camada de dados do mesmo app através de App Intents e através de um servidor MCP. A camada visual é a terceira superfície da mesma stack: entidades tipadas para a IA do sistema, formato de arquivo para agentes cross-LLM e Liquid Glass para o humano no dispositivo.8

FAQ

Posso usar .glassEffect() em plataformas que não sejam iOS 26?

O modificador .glassEffect() é iOS 26+, iPadOS 26+, macOS 26+, watchOS 26+, tvOS 26+, visionOS 26+. Plataformas pré-26 têm .background(.regularMaterial) e similares, que produzem efeitos de glass fosco mas não a nova refração do Liquid Glass.1

O GlassEffectContainer muda o visual?

Elementos glass envolvidos em container podem fundir suas shapes quando suas regras de espaçamento causam sobreposição. Sem um container, cada .glassEffect() é independente. Para apps onde elementos glass devem se fundir fluidamente durante animação, GlassEffectContainer é a ferramenta certa. Para apps onde cada elemento glass permanece distinto, um container é overhead.1

Por que não usar Text diretamente com .foregroundStyle(.thinMaterial)?

thinMaterial é um material padrão, não Liquid Glass. O visual é um overlay de glass fosco, não o efeito de glass refrativo com curvatura de luz do Liquid Glass.3 Para texto que deve parecer especificamente o novo material, .glassEffect(.clear, in: customShape) é o caminho suportado.

Como capturo um screenshot do Liquid Glass para marketing?

Efeitos glass são renderizados em GPU em runtime, então screenshots são tirados do simulador ou dispositivo com o efeito já aplicado. As imagens oficiais de referência do Liquid Glass da Apple vêm das páginas de documentação do HIG e das sessões da WWDC 2025.3

O GlassTextShape funciona para texto arbitrário ou apenas dígitos?

Qualquer string que o Core Text consiga fazer layout funciona. O Return usa para dígitos e dois-pontos, mas o mesmo Shape funciona para letras, símbolos, emojis (com a fonte certa) ou strings mistas. A performance é limitada pela contagem de glifos; um parágrafo longo renderizado como glass seria caro, mas um timer de seis caracteres é trivial.


Três padrões, uma regra e uma API que pulei deliberadamente. O Liquid Glass é a terceira superfície de um app no iOS 26+, sentado no topo de entidades tipadas e formatos de arquivo compartilhados. A API de uma linha é real. A regra do HIG por baixo dela é o que faz o one-liner funcionar.

Referências


  1. Apple Developer, “Applying Liquid Glass to custom views”. Documentação para o modificador glassEffect(_:in:), GlassEffectContainer, glassEffectUnion(id:namespace:), glassEffectID(_:in:) e GlassEffectTransition. Variante padrão .regular, shape padrão Capsule

  2. O Return do autor, um app de timer de meditação publicado na App Store em 21 de abril de 2026, disponível para iPhone, iPad, Mac, Apple Watch e Apple TV. Usa SwiftUI, SwiftData e HealthKit em iOS 26+ / macOS 26+. 

  3. Apple Developer, “Materials” Human Interface Guidelines. Define a regra de camada funcional vs camada de conteúdo para o Liquid Glass: “Don’t use Liquid Glass in the content layer.” Lista as variantes regular e clear e seus usos pretendidos. 

  4. Código de produção em Return/Return/ContentView.swift (sete locais de chamada de .glassEffect()), Return/Return/GlassTimerText.swift (um local de chamada em GlassDigitCell) e Return/ReturnTV/TVContentView.swift (um local de chamada no indicador “Paused” do tvOS). Total nove. Mais Return/Return/VideoBackgroundView.swift, que renderiza as imagens de capa baseadas em tema e o vídeo em loop através dos quais os elementos glass refratam. 

  5. Código de produção em Return/Return/GlassTextShape.swift. O wrapper conformante a Shape ao redor do Core Text. Criado em 26 de novembro de 2025, incluído na v1.0 publicada na App Store. 

  6. Código de produção em Return/Return/GlassTimerText.swift. Views GlassDigitCell, GlassTimerText e GlassTimerDisplay. Implementa o layout de células de largura fixa, o reflexo em espelho e o gating de reduce-motion. 

  7. Apple Developer, valor de environment “accessibilityReduceMotion”. Apps devem honrar a preferência de movimento do usuário; animações de morph padrão no Liquid Glass devem ser condicionadas ao valor. 

  8. Análise do autor em App Intents Are Apple’s New API to Your App e Two Agent Ecosystems, One Shopping List. O modelo de três superfícies: App Intents para Apple Intelligence, MCP para agentes cross-LLM, Liquid Glass para o humano no dispositivo. 

  9. Apple Developer, “glassEffect(_:in:isEnabled:)” em View. O parâmetro in: aceita qualquer tipo conformante a Shape. O shape padrão é Capsule

  10. Apple Developer, “Shape” protocol. Um Shape é qualquer tipo que produza um Path para um dado retângulo. Shapes customizados podem envolver dados arbitrários de CGPath

  11. Apple Developer, “Core Text Programming Guide” e CTLineCreateWithAttributedString. Core Text é o motor de texto de mais baixo nível usado para fazer layout de strings atribuídas em runs de glifos e extrair paths por glifo. 

  12. Apple Developer, “flipsForRightToLeftLayoutDirection(_:)”. Sobrescreve explicitamente o espelhamento RTL em uma View independentemente do valor do environment \.layoutDirection ao redor. 

  13. Apple, “WWDC 2025 Highlights” via Apple Newsroom. Liquid Glass anunciado como o material de design unificador em iOS 26, iPadOS 26, macOS 26, watchOS 26, tvOS 26 e visionOS 26. Sessões: “Meet Liquid Glass” (WWDC 2025), “Build a SwiftUI app with Liquid Glass”

  14. Apple Developer, “LinearGradient”, “scaleEffect(x:y:anchor:)”, “mask(_:)”. Primitivas padrão do SwiftUI, todas disponíveis desde iOS 13. 

Artigos relacionados

HealthKit + SwiftUI no iOS 26: autorização, tipos de amostra e padrões multiplataforma a partir do envio de dois apps

Padrões reais de produção do Water (rastreamento de água, HKQuantitySample) e do Return (sessões mindful, HKCategorySamp…

16 min de leitura

Internos do @Observable: A macro, o registrar e o que o ObservableObject errou

O @Observable substitui o modelo de transmissão do ObservableObject por rastreamento de acesso por propriedade. A expans…

10 min de leitura

Gosto é infraestrutura

À medida que agentes geram mais do que vai para produção, o teto de qualidade é definido por quão bem você codifica julg…

6 min de leitura