UIBezierPath: o que é, métodos de desenho e como funciona

Autor: IT Sectr Publicado: 2026-07-21 Tempo de leitura: 8 min

UIBezierPath é uma classe do UIKit que encapsula um caminho vetorial para gráficos 2D no iOS. Ela combina a descrição geométrica do contorno com capacidades de desenho, permitindo criar linhas, curvas Bezier, arcos e retângulos. Ao contrário do CGPath, o UIBezierPath contém seus próprios métodos de desenho que funcionam diretamente no contexto gráfico atual. De acordo com Apple Developer Documentation, 2026, o UIBezierPath suporta todas as operações padrão do Quartz 2D em um invólucro orientado a objetos.

Pontos principais

  • UIBezierPath é um invólucro orientado a objetos do CGPath para trabalhar com caminhos vetoriais no UIKit.
  • move(to:) e addLine(to:) definem segmentos de reta do caminho.
  • addQuadCurve(to:controlPoint:) e addCurve(to:controlPoint1:controlPoint2:) constroem curvas Bezier.
  • addArc(withCenter:radius:startAngle:endAngle:clockwise:) cria arcos e setores.
  • fill e stroke — desenho direto do caminho no contexto atual sem usar objetos adicionais.

O que é UIBezierPath?

UIBezierPath é uma classe do framework UIKit que herda de NSObject e implementa NSCopying, NSSecureCoding. Ela fornece uma API Objective-C/Swift de alto nível para construir e desenhar caminhos vetoriais. Internamente, o UIBezierPath armazena uma referência ao CGPathRef — um objeto do Core Graphics — mas adiciona métodos convenientes para desenho, modificação de geometria e gerenciamento de estilos.

A principal vantagem do UIBezierPath sobre o uso direto do CGPath são os métodos de desenho integrados. Chamar fill() ou stroke() em uma instância do UIBezierPath configura automaticamente o contexto e desenha o caminho. A classe também suporta as propriedades lineWidth, lineCapStyle, lineJoinStyle, miterLimit e flatness, permitindo controlar a aparência sem um objeto separado para armazenar estilos.

O UIBezierPath é usado na maioria dos aplicativos iOS para desenho personalizado dentro de UIView: desde ícones simples até gráficos animados complexos. O método draw(_:) da classe UIView é o local principal onde os desenvolvedores criam e desenham o UIBezierPath. A classe é totalmente compatível com Core Animation e pode ser usada para animação de caminhos através de CAShapeLayer e CABasicAnimation.

Linhas retas e retângulos

O método move(to:) move o ponto inicial do caminho para as coordenadas especificadas sem desenhar. Esta é uma chamada obrigatória antes de construir qualquer segmento. addLine(to:) adiciona um segmento reto da posição atual até o ponto indicado. O método close() fecha o contorno desenhando uma linha do último ponto até o primeiro ponto do último move(to:).

Retângulos com cantos arredondados

UIBezierPath fornece vários inicializadores convenientes para formas prontas. init(rect:) cria um retângulo, init(roundedRect:cornerRadius:) cria um retângulo com cantos arredondados. O parâmetro UIRectCorner permite arredondar apenas os cantos selecionados, como topLeft e bottomRight, deixando os demais retos. Isso é amplamente usado para criar botões e cartões personalizados.

init(ovalIn:) cria uma elipse inscrita no retângulo especificado. Se o retângulo for um quadrado, a elipse se torna um círculo. init(roundedRect:byRoundingCorners:cornerRadii:) é a opção mais flexível, permitindo definir raios diferentes para cada canto. Este inicializador foi introduzido no iOS 6 e continua sendo o padrão para criar contêineres arredondados.

swift
let path = UIBezierPath()
path.move(to: CGPoint(x: 50, y: 50))
path.addLine(to: CGPoint(x: 200, y: 50))
path.addLine(to: CGPoint(x: 200, y: 150))
path.addLine(to: CGPoint(x: 125, y: 200))
path.addLine(to: CGPoint(x: 50, y: 150))
path.close()

Curvas Bezier: quadráticas e cúbicas

addQuadCurve(to:controlPoint:) adiciona uma curva Bezier quadrática com um ponto de controle. Este tipo de curva é usado para curvaturas suaves simples quando se deseja minimizar os cálculos. Uma curva quadrática é sempre uma parábola e está garantidamente dentro do triângulo formado pelos pontos inicial, de controle e final.

Curvas Bezier cúbicas

addCurve(to:controlPoint1:controlPoint2:) adiciona uma curva Bezier cúbica com dois pontos de controle. As curvas cúbicas são usadas em todos os editores vetoriais modernos e fontes TrueType. Dois pontos de controle fornecem mais graus de liberdade para um controle preciso da forma. Este método é recomendado para construir contornos orgânicos e complexos.

Ao construir curvas, é importante manter o princípio de continuidade — a suavidade no ponto de conexão dos segmentos. Para continuidade C1 (tangente), o ponto de controle da próxima curva deve estar na mesma linha que o ponto de controle da anterior. Para continuidade C2 (curvatura), é necessária uma coordenação mais complexa, que é fornecida automaticamente no CAShapeLayer ao animar entre dois UIBezierPath com o mesmo número de pontos de controle.

MétodoTipoPontos de controleGrau
addQuadCurveBezier quadrática12
addCurveBezier cúbica23
addArcArco

Arcos e circunferências

addArc(withCenter:radius:startAngle:endAngle:clockwise:) adiciona um arco circular com os parâmetros especificados. Os ângulos são indicados em radianos em relação ao centro do círculo. O ângulo zero corresponde à direção para a direita (3 horas em um mostrador de relógio). O parâmetro clockwise determina a direção: true para sentido horário, false para anti-horário. Os arcos são essenciais para gráficos de pizza, velocímetros e anéis de progresso interativos.

Circunferências e setores

Para uma circunferência completa, use startAngle = 0 e endAngle = .pi * 2. Para criar um setor (como parte de um gráfico de pizza), use addArc seguido de addLine(to:) ao centro e close(). O UIBezierPath não tem um método addCircle embutido — um círculo é criado via init(ovalIn:) com um retângulo quadrado ou via addArc com um ângulo completo.

O método addArc(withCenter:radius:startAngle:endAngle:clockwise:) executa automaticamente move(to:) para o ponto inicial do arco se a posição atual não coincidir. Se a posição atual for diferente, uma linha reta é desenhada entre ela e o início do arco. Este comportamento difere do Core Graphics, onde um move(to:) explícito é necessário antes de cada novo contorno.

swift
let center = CGPoint(x: 150, y: 150)
let slice = UIBezierPath()
slice.move(to: center)
slice.addArc(
    withCenter: center,
    radius: 100,
    startAngle: 0,
    endAngle: .pi * 0.75,
    clockwise: true
)
slice.close()

Preenchimento e traçado do caminho

fill() preenche o interior do caminho com a cor fillColor atual ou a cor definida no contexto gráfico através de setFill(). Para caminhos com autointerseções, a regra de preenchimento é determinada pela propriedade usesEvenOddFillRule. Se for true, a regra par-ímpar é usada: um ponto é considerado dentro da forma se um raio a partir dele cruzar o contorno um número ímpar de vezes.

Configuração do traçado

stroke() desenha o contorno do caminho com as configurações atuais de lineWidth, lineCapStyle e lineJoinStyle. lineCapStyle define a forma das extremidades dos segmentos abertos: .butt (corte reto), .round (semicircular), .square (quadrado com saliência). lineJoinStyle define a forma das junções dos cantos: .miter (agudo), .round (arredondado), .bevel (chanfrado).

Para linhas tracejadas, usa-se a propriedade setLineDash(_:count:phase:). Ela aceita um array de comprimentos alternados de traços e espaços, o número de elementos e a fase inicial. A renderização do tracejado é realizada durante a rasterização do caminho — padrões complexos não aumentam a complexidade geométrica do contorno. O CAShapeLayer suporta animação da propriedade strokeEnd para um efeito de “desenho” do início ao fim.

swift
override func draw(_ rect: CGRect) {
    let path = UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 200, height: 200))
    UIColor.blue.setFill()
    UIColor.black.setStroke()
    path.lineWidth = 4
    path.fill()
    path.stroke()
}

Exemplo de criação de uma figura complexa

Vamos criar um indicador de progresso personalizado em forma de anel usando UIBezierPath. O anel é construído a partir de dois arcos do mesmo raio com cores de traçado diferentes. O primeiro arco é um círculo completo em cinza (fundo), o segundo é um segmento que mostra o progresso. Para animação, são usados CAShapeLayer e CABasicAnimation.

swift
class RingView: UIView {

    private let progressLayer = CAShapeLayer()

    override func layoutSubviews() {
        super.layoutSubviews()
        let center = CGPoint(x: bounds.midX, y: bounds.midY)
        let radius = bounds.width * 0.4
        let lineWidth: CGFloat = 12

        let backgroundRing = UIBezierPath()
        backgroundRing.addArc(withCenter: center, radius: radius,
                          startAngle: -.pi / 2, endAngle: .pi * 1.5, clockwise: true)

        progressLayer.path = backgroundRing.cgPath
        progressLayer.strokeColor = UIColor.systemBlue.cgColor
        progressLayer.lineWidth = lineWidth
        progressLayer.lineCap = .round
        progressLayer.fillColor = UIColor.clear.cgColor
        progressLayer.strokeEnd = 0
        layer.addSublayer(progressLayer)
    }

    func animateProgress(to value: CGFloat) {
        CABasicAnimation(keyPath: "strokeEnd").apply {
            $0.toValue = value
            $0.duration = 1.5
            $0.timingFunction = CAMediaTimingFunction(name: .easeOut)
            progressLayer.add($0, forKey: nil)
        }
        progressLayer.strokeEnd = value
    }
}

Neste exemplo, UIBezierPath é usado para criar um contorno circular, que é então passado para CAShapeLayer através da propriedade cgPath. A animação de strokeEnd de 0 a 1 visualiza o preenchimento do anel. Esta abordagem é usada em indicadores de carregamento, rastreadores de fitness e widgets de progresso. O método layoutSubviews garante a reconstrução do caminho quando o tamanho da View muda.

lineCap = .round adiciona extremidades arredondadas ao arco, dando ao indicador uma aparência mais cuidada. A propriedade strokeEnd é uma propriedade animável do CAShapeLayer que não requer redesenhar todo o contorno a cada quadro. A animação é executada inteiramente na GPU através do Core Animation, garantindo 60 FPS sem carga na CPU.

Perguntas frequentes

Como o UIBezierPath difere do CGPath?

UIBezierPath é um invólucro orientado a objetos em torno do CGPath que contém métodos fill() e stroke() embutidos. CGPath é um objeto C imutável do Core Graphics que requer desenho explícito através de CGContext. UIBezierPath é mais conveniente para UIKit, enquanto CGPath é mais eficiente para reutilização.

Como arredondar apenas os cantos superiores de um retângulo?

Use init(roundedRect:byRoundingCorners:cornerRadii:) com os parâmetros .topLeft e .topRight para roundedRect. Este é o único método do UIBezierPath que permite arredondar seletivamente cantos sem criar um caminho composto complexo.

Como reutilizar UIBezierPath com estilos diferentes?

A propriedade cgPath retorna um CGPathRef imutável que pode ser passado para CAShapeLayer ou usado com cores e espessuras diferentes. Modificações no UIBezierPath (movimento de pontos) não afetam o cgPath obtido anteriormente até que seja explicitamente atualizado.

Por que fill() não cobre todo o caminho?

Verifique usesEvenOddFillRule — se o contorno tiver autointerseções, a regra par-ímpar pode deixar áreas não preenchidas. Defina usesEvenOddFillRule = false para a regra de preenchimento padrão non-zero winding.

Como animar a forma do UIBezierPath?

Use CABasicAnimation com o caminho chave “path” no CAShapeLayer. Ambos os estados do caminho devem conter o mesmo número de segmentos e pontos de controle — caso contrário, a animação será irregular ou falhará.

Resumo

  • UIBezierPath é uma classe orientada a objetos do UIKit para trabalhar com caminhos vetoriais e gráficos 2D.
  • move(to:) e addLine(to:) são métodos básicos para construir linhas retas e polígonos.
  • addQuadCurve e addCurve criam curvas Bezier quadráticas e cúbicas com um e dois pontos de controle.
  • addArc desenha arcos circulares com controle flexível de ângulos e direção.
  • fill() e stroke() realizam o desenho diretamente no contexto gráfico atual.
  • Os inicializadores init(roundedRect:) e init(ovalIn:) aceleram a criação de formas padrão.
  • A propriedade cgPath permite integrar UIBezierPath com Core Animation e CAShapeLayer para animação.

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.

Discutir o projeto

Leia também