UIBezierPath: vad är det, ritmetoder och hur det fungerar

Författare: IT Sectr Publicerad: 2026-07-21 Lästid: 8 min

UIBezierPath — en klass från UIKit som kapslar in en vektorbana för 2D-grafik i iOS. Den kombinerar den geometriska beskrivningen av en kontur med ritmöjligheter, vilket gör det möjligt att skapa linjer, Bézier-kurvor, bågar och rektanglar. Till skillnad från CGPath innehåller UIBezierPath egna ritmetoder direkt i den aktuella grafiska kontexten. Enligt Apple Developer Documentation, 2026 stöder UIBezierPath alla standard Quartz 2D-operationer i ett objektorienterat omslag.

Huvudpunkter

  • UIBezierPath — objektorienterat omslag av CGPath för arbete med vektorkonturer i UIKit.
  • move(to:) och addLine(to:) definierar raka linjesegment av banan.
  • addQuadCurve(to:controlPoint:) och addCurve(to:controlPoint1:controlPoint2:) bygger Bézier-kurvor.
  • addArc(withCenter:radius:startAngle:endAngle:clockwise:) skapar bågar och sektorer.
  • fill och stroke — direktritning av banan i den aktuella kontexten utan att använda ytterligare objekt.

Vad är UIBezierPath?

UIBezierPath — en klass i UIKit-ramverket, som ärver NSObject och implementerar NSCopying, NSSecureCoding. Den tillhandahåller ett högnivå Objective-C/Swift API för att bygga och rita vektorkonturer. Internt lagrar UIBezierPath en referens till CGPathRef — ett Core Graphics-objekt, men lägger till bekväma metoder för ritning, geometriändring och stilhantering.

Den främsta fördelen med UIBezierPath jämfört med direkt användning av CGPath är inbyggda ritmetoder. Anrop av fill() eller stroke() på en UIBezierPath-instans konfigurerar automatiskt kontexten och ritar banan. Klassen stöder också egenskaperna lineWidth, lineCapStyle, lineJoinStyle, miterLimit och flatness, vilket gör det möjligt att hantera utseendet utan ett separat objekt för stilagring.

UIBezierPath används i de flesta iOS-applikationer för anpassad ritning inuti UIView: från enkla ikoner till komplexa animerade grafer. Metoden draw(_:) i UIView-klassen är den huvudsakliga platsen där utvecklare skapar och ritar UIBezierPath. Klassen är fullt kompatibel med Core Animation och kan användas för bananimering via CAShapeLayer och CABasicAnimation.

Raka linjer och rektanglar

Metoden move(to:) flyttar banans startpunkt till de angivna koordinaterna utan att rita. Detta är ett obligatoriskt anrop före byggandet av ett segment. addLine(to:) lägger till ett rakt segment från den aktuella positionen till den angivna punkten. För att stänga konturen används metoden close(), som drar en linje från den sista punkten till den första punkten av den senaste move(to:).

Rektanglar med rundade hörn

UIBezierPath tillhandahåller flera bekväma initierare för färdiga former. init(rect:) skapar en rektangel, init(roundedRect:cornerRadius:) — en rektangel med rundade hörn. Parametern UIRectCorner gör det möjligt att runda endast valda hörn, till exempel topLeft och bottomRight, medan de andra förblir raka. Detta används ofta för att skapa anpassade knappar och kort.

init(ovalIn:) skapar en ellips inskriven i den angivna rektangeln. Om rektangeln är en kvadrat förvandlas ellipsen till en cirkel. init(roundedRect:byRoundingCorners:cornerRadii:) — den mest flexibla varianten, som gör det möjligt att ställa in olika radier för varje hörn. Denna initierare dök upp i iOS 6 och förblir standarden för att skapa rundade containrar.

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()

Bézier-kurvor: kvadratiska och kubiska

addQuadCurve(to:controlPoint:) lägger till en kvadratisk Bézier-kurva med en kontrollpunkt. Denna kurvtyp används för enkla mjuka böjningar när man vill minimera antalet beräkningar. Den kvadratiska kurvan är alltid en parabel och ligger garanterat inom triangeln som bildas av start-, kontroll- och slutpunkterna.

Kubiska Bézier-kurvor

addCurve(to:controlPoint1:controlPoint2:) lägger till en kubisk Bézier-kurva med två kontrollpunkter. Kubiska kurvor används i alla moderna vektorredigerare och TrueType-teckensnitt. Två kontrollpunkter ger fler frihetsgrader för exakt kontroll av kurvformen. Denna metod rekommenderas för att bygga organiska och komplexa konturer.

Vid byggande av kurvor är det viktigt att följa kontinuitetsprincipen — kurvans jämnhet vid segmentens föreningspunkt. För C1-kontinuitet (tangent) måste kontrollpunkten för nästa kurva ligga på samma raka linje som kontrollpunkten för den föregående. För C2-kontinuitet (krökning) krävs en mer komplex anpassning, som automatiskt säkerställs i CAShapeLayer vid animering mellan två UIBezierPath med samma antal kontrollpunkter.

MetodTypKontrollpunkterGrad
addQuadCurveKvadratisk Bézier12
addCurveKubisk Bézier23
addArcBåge

Bågar och cirklar

addArc(withCenter:radius:startAngle:endAngle:clockwise:) lägger till en cirkelbåge med de angivna parametrarna. Vinklar anges i radianer i förhållande till cirkelns centrum. Noll vinkel motsvarar riktningen åt höger (klockan 3 på urtavlan). Parametern clockwise bestämmer riktningen: true — medurs, false — moturs. Bågar är oumbärliga för cirkeldiagram, hastighetsmätare och interaktiva framstegsringar.

Cirkel och sektorer

För en hel cirkel räcker startAngle = 0 och endAngle = .pi * 2. För att skapa en sektor (som en del av ett cirkeldiagram) använd addArc följt av addLine(to:) till centrum och close(). UIBezierPath har ingen inbyggd addCircle-metod — en cirkel skapas via init(ovalIn:) med en kvadratisk rektangel eller via addArc med full vinkel.

Metoden addArc(withCenter:radius:startAngle:endAngle:clockwise:) utför automatiskt move(to:) till bågens startpunkt om den aktuella positionen inte sammanfaller med den. Om den aktuella positionen är annorlunda, dras en rak linje mellan den och bågens början. Detta beteende skiljer sig från arbete med Core Graphics, där en explicit move(to:) krävs före varje ny kontur.

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()

Fyllning och streckning av banan

fill() fyller banans inre område med den aktuella fillColor-färgen eller färgen som ställts in i den grafiska kontexten via setFill(). För banor med självkorsningar bestäms fyllningsregeln av egenskapen usesEvenOddFillRule. Om den är true tillämpas even-odd-regeln: en punkt anses vara innanför formen om en stråle från den skär konturen ett udda antal gånger.

Konfiguration av streckning

stroke() ritar banans kontur med de aktuella inställningarna för lineWidth, lineCapStyle och lineJoinStyle. lineCapStyle bestämmer formen på ändarna av öppna segment: .butt (rakt snitt), .round (halvcirkelformad), .square (fyrkantig med utskott). lineJoinStyle bestämmer formen på förbindningshörn: .miter (vass), .round (rundad), .bevel (avskuren).

För streckade linjer används egenskapen setLineDash(_:count:phase:). Den tar emot en array av längder av växlande streck och mellanrum, antalet element och en startfas. Visualiseringen av den streckade linjen sker i rastreringsfasen av banan — komplexa mönster ökar inte konturens geometriska komplexitet. CAShapeLayer stöder animering av egenskapen strokeEnd för effekten av att “rita” en linje från början till slut.

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()
}

Exempel på att skapa en komplex figur

Låt oss skapa en anpassad framstegsindikator i form av en ring med UIBezierPath. Ringen byggs av två bågar med samma radie men olika streckningsfärg. Den första bågen är en hel grå cirkel (bakgrund), den andra är ett segment som visar framsteg. För animering används CAShapeLayer och 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
    }
}

I detta exempel används UIBezierPath för att skapa en cirkulär kontur, som sedan skickas till CAShapeLayer via egenskapen cgPath. Animeringen av strokeEnd från 0 till 1 visualiserar fyllningen av ringen. Detta tillvägagångssätt används i laddningsindikatorer, fitness-trackers och framstegswidgetar. Metoden layoutSubviews garanterar ombyggnad av banan vid ändring av View-dimensioner.

lineCap = .round lägger till rundade ändar på bågen, vilket ger indikatorn ett mer ordnat utseende. Egenskapen strokeEnd är en animerbar egenskap hos CAShapeLayer som inte kräver omritning av hela konturen i varje bildruta. Animeringen utförs helt på GPU via Core Animation, vilket säkerställer 60 FPS utan CPU-belastning.

Vanliga frågor

Vad skiljer UIBezierPath från CGPath?

UIBezierPath — objektorienterat omslag av CGPath som innehåller inbyggda fill()- och stroke()-metoder. CGPath är ett oföränderligt C Core Graphics-objekt som kräver explicit ritning via CGContext. UIBezierPath är bekvämare för UIKit, CGPath är effektivare för återanvändning.

Hur rundar jag endast de övre hörnen på en rektangel?

Använd init(roundedRect:byRoundingCorners:cornerRadii:) med parametern .topLeft och .topRight för roundedRect. Detta är den enda UIBezierPath-metoden som möjliggör selektiv avrundning av hörn utan att skapa en komplex sammansatt bana.

Hur återanvänder jag UIBezierPath med olika stilar?

Egenskapen cgPath returnerar en oföränderlig CGPathRef som kan skickas till CAShapeLayer eller användas med olika färger och tjocklekar. Ändringar av UIBezierPath (flyttning av punkter) påverkar inte tidigare erhållen cgPath förrän explicit uppdatering.

Varför fyller fill() inte hela banan?

Kontrollera usesEvenOddFillRule — om konturen har självkorsningar kan even-odd-regeln lämna områden ofyllda. Ställ in usesEvenOddFillRule = false för standardregeln för non-zero winding-fyllning.

Hur animerar jag formen på UIBezierPath?

Använd CABasicAnimation med nyckelsökvägen “path” på CAShapeLayer. Båda banornas tillstånd måste innehålla samma antal segment och kontrollpunkter — annars kommer animeringen att vara hackig eller inte fungera.

Sammanfattning

  • UIBezierPath — objektorienterad UIKit-klass för arbete med vektorkonturer och 2D-grafik.
  • move(to:) och addLine(to:) — grundläggande metoder för att bygga raka linjer och polygoner.
  • addQuadCurve och addCurve skapar kvadratiska och kubiska Bézier-kurvor med en och två kontrollpunkter.
  • addArc ritar cirkelbågar med flexibel kontroll av vinklar och riktning.
  • fill() och stroke() utför ritning direkt i den aktuella grafiska kontexten.
  • Initierarna init(roundedRect:) och init(ovalIn:) påskyndar skapandet av standardformer.
  • Egenskapen cgPath möjliggör integration av UIBezierPath med Core Animation och CAShapeLayer för animering.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också