draw(_:) / drawRect — är metoden i UIView-klassen (i Swift) och dess motsvarighet i Objective-C (drawRect:), som ansvarar för att rendera innehållet i vyn med Core Graphics. Systemet anropar denna metod automatiskt vid första visningen av vyn på skärmen och efter anrop av setNeedsDisplay(). Enligt Apple Documentation (2025) är draw(_:) den enda metoden där utvecklaren har tillgång till den aktuella skärmens grafikkontext för anpassad ritning. Överskrivning av draw(_:) ger full kontroll över komponentens utseende — från enkla geometriska former till komplex animerad grafik.
Huvudpunkter
draw(_:) — är en instansmetod i UIView som UIKit anropar för att rendera innehållet i vyn. Inuti denna metod får utvecklaren tillgång till grafikkontexten CGContext och använder Core Graphics API för att rita linjer, fyllningar, text och bilder. drawRect: i Objective-C utför samma funktion, men med annan syntax: den enda parametern är en CGRect som anger området för omritning.
Enligt Apple Engineering (2024) fungerar draw(_:) genom CPU-rendering av Bitmap Graphics Context, vilket ger maximal flexibilitet men kräver mer resurser jämfört med CALayer. Beslutet att använda draw(_:) fattas baserat på grafikens komplexitet och prestandakrav.
I Swift deklareras metoden som override func draw(_ rect: CGRect), där rect är rektangeln som måste ritas om. I Objective-C är signaturen - (void)drawRect:(CGRect)rect. Parametern rect kan vara mindre än vyns bounds vid partiell omritning via setNeedsDisplay(_:).
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rect);
}
Systemet anropar automatiskt draw(_:) i strikt definierade scenarier. Att förstå dessa triggers hjälper till att undvika onödig omritning och optimera vyns prestanda. Nedan listas alla fall av automatisk anropning av metoden.
Apple-dokumentationen varnar: anropa aldrig draw(_:) direkt. Systemet bestämmer själv när ritning ska utföras och direkt anrop stör den interna cachningsmekanismen. För att begära omritning, använd alltid setNeedsDisplay() eller setNeedsDisplay(_:).
Att överskriva draw(_:) i Swift börjar med att hämta grafikkontexten och efterföljande Core Graphics-anrop. Det rekommenderas att skapa separata metoder för logiska ritblock — detta förbättrar kodens läsbarhet och testbarhet.
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
// Linjeparametrar
context.setStrokeColor(UIColor.darkGray.cgColor)
context.setLineWidth(2.0)
// Rita en triangel
context.move(to: CGPoint(x: rect.midX, y: rect.minY + 10))
context.addLine(to: CGPoint(x: rect.maxX - 10, y: rect.maxY - 10))
context.addLine(to: CGPoint(x: rect.minX + 10, y: rect.maxY - 10))
context.closePath()
context.strokePath()
}
I detta exempel ritar draw(_:) en triangel med en mörkgrå kontur som är 2 pixlar tjock. Anrop av super.draw(rect) i början av metoden rekommenderas av Apple för att bevara förälderns ritlogik, även om standardimplementeringen av draw(_:) i UIView är tom.
Varje anrop av draw(_:) bör ge identiskt resultat vid samma indata. Detta gör det möjligt för systemet att cachelagra resultatet och inte anropa draw(_:) igen om vyns innehåll inte har ändrats. Använd inte slumpmässiga värden, systemtid eller nätverksförfrågningar inuti draw(_:).
drawRect: — historiskt den första versionen av metoden, som dök upp i iOS 2.0 tillsammans med Objective-C. I Swift döptes metoden om till draw(_:) med användning av den externa parametern _. Funktionellt är metoderna identiska: båda tar emot en CGRect för omritningsområdet och använder UIGraphicsGetCurrentContext() för att komma åt grafikkontexten.
| Egenskap | draw(_:) (Swift) | drawRect: (Objective-C) |
|---|---|---|
| Signatur | override func draw(_ rect: CGRect) | - (void)drawRect:(CGRect)rect |
| Super-anrop | super.draw(rect) | [super drawRect:rect] |
| Kontext | UIGraphicsGetCurrentContext() | UIGraphicsGetCurrentContext() |
| Parameter rect | rect: CGRect | CGRect rect |
| Prestanda | Identisk | Identisk |
Vid migrering av ett projekt från Objective-C till Swift är omdöpning av metoden en av de första uppgifterna. Xcode tillhandahåller en automatisk omvandlare, men drawRect: kräver manuell uppdatering till draw(_:). Enligt Apple (2024) är Swift-versionen draw(_:) att föredra för nya projekt.
draw(_:) körs på CPU och en icke-optimal implementering kan orsaka bildrutebortfall och låg prestanda. Apple rekommenderar flera beprövade tillvägagångssätt för att påskynda ritningen.
Varje Core Graphics-operation (move(to:), addLine(to:), strokePath) har overhead. Gruppera operationer och använd CGPath för komplexa former — sökvägen skapas en gång och återanvänds vid varje anrop av draw(_:).
UIBezierPath — är ett Objective-C-omslag runt CGPath som ger ett enkelt API för att skapa former. Skapa UIBezierPath i förväg (t.ex. i initieraren) och anropa helt enkelt fill() eller stroke() inuti draw(_:).
private let starPath: UIBezierPath = {
let path = UIBezierPath()
// Bygga en stjärnform
path.move(to: CGPoint(x: 50, y: 0))
for i in 1...5 {
let angle = CGFloat(i) * 4 * CGFloat.pi / 5
path.addLine(to: CGPoint(x: 50 + 40 * cos(angle),
y: 50 + 40 * sin(angle)))
}
path.close()
return path
}()
override func draw(_ rect: CGRect) {
UIColor.systemYellow.setFill()
starPath.fill()
}
Utvecklare gör ofta samma misstag när de överskriver draw(_:). Kännedom om dessa mönster hjälper till att undvika buggar och prestandaförsämring. Låt oss titta på de vanligaste problemen och deras lösningar.
Genom att följa dessa regler säkerställer du stabil och snabb ritning av anpassade vyer i alla iOS-projekt. Profilera draw(_:) via Instruments (Core Animation) för att se verklig exekveringstid och flaskhalsar.
Vanliga frågor
Nej, direkt anrop av draw(_:) är förbjudet enligt Apple-dokumentationen. Systemet hanterar själv ritcykeln. För att begära omritning, använd setNeedsDisplay(), som korrekt markerar vyn som behövande uppdatering i närmaste renderingscykel.
Funktionellt är dessa metoder identiska. drawRect: används i Objective-C, draw(_:) — i Swift. Båda tar emot en CGRect för omritningsområdet och använder samma Core Graphics-kontext via UIGraphicsGetCurrentContext().
Apple optimerar rendering: om UIView inte har en överskriven draw(_:) skapar systemet ingen bitmappskontext för den. Detta sparar minne. Om överskrivning finns men metoden inte anropas — kontrollera att vyens ram inte är noll och att vyn är synlig.
Endast vid behov: första renderingen, efter setNeedsDisplay(), vid ändring av bounds med contentMode = .redraw. I statiskt tillstånd anropas draw(_:) inte igen, vilket sparar CPU- och batteriresurser.
Apple rekommenderar att anropa super.draw(rect) i början av den överskrivna metoden. Även om den nuvarande UIView-implementeringen är tom säkerställer super-anropet kompatibilitet med framtida versioner av UIKit och är god praxis.
Sammanfattning
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.
Läs också