draw(_:) / drawRect — is de methode van de UIView-klasse (in Swift) en het equivalent in Objective-C (drawRect:), die verantwoordelijk is voor het renderen van de inhoud van de view met Core Graphics. Het systeem roept deze methode automatisch aan bij de eerste weergave van de view op het scherm en na het aanroepen van setNeedsDisplay(). Volgens Apple Documentation (2025) is draw(_:) de enige methode waarin de ontwikkelaar toegang heeft tot de grafische context van het huidige scherm voor aangepast tekenen. Het overschrijven van draw(_:) geeft volledige controle over het uiterlijk van het component — van eenvoudige geometrische vormen tot complexe geanimeerde graphics.
Belangrijkste
draw(_:) — is een UIView-instantiemethode die UIKit aanroept voor het renderen van de inhoud van de view. Binnen deze methode krijgt de ontwikkelaar toegang tot de grafische context CGContext en gebruikt hij de Core Graphics API om lijnen, vullingen, tekst en afbeeldingen te tekenen. drawRect: in Objective-C vervult dezelfde functie, maar met een andere syntaxis: de enige parameter is CGRect die het te hertekenen gebied specificeert.
Volgens Apple Engineering (2024) werkt draw(_:) via CPU-rendering Bitmap Graphics Context, wat maximale flexibiliteit biedt, maar meer middelen vereist in vergelijking met CALayer. De beslissing om draw(_:) te gebruiken wordt genomen op basis van de complexiteit van de graphics en de prestatienvereisten.
In Swift wordt de methode gedeclareerd als override func draw(_ rect: CGRect), waarbij rect de rechthoek is die opnieuw moet worden getekend. In Objective-C is de handtekening - (void)drawRect:(CGRect)rect. De parameter rect kan kleiner zijn dan de bounds van de view bij gedeeltelijk hertekenen via setNeedsDisplay(_:).
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rect);
}
Het systeem roept draw(_:) automatisch aan in strikt gedefinieerde scenario's. Inzicht in deze triggers helpt onnodig hertekenen te voorkomen en de prestaties van de view te optimaliseren. Hieronder worden alle gevallen van automatische aanroep van de methode opgesomd.
Apple-documentatie waarschuwt: roep draw(_:) nooit direct aan. Het systeem beslist zelf wanneer het tekenen moet uitvoeren en een directe aanroep verstoort het interne cachingmechanisme. Gebruik altijd setNeedsDisplay() of setNeedsDisplay(_:) om hertekenen aan te vragen.
Het overschrijven van draw(_:) in Swift begint met het verkrijgen van de grafische context en daaropvolgende Core Graphics-aanroepen. Het wordt aanbevolen om afzonderlijke methoden te maken voor logische tekenblokken — dit verbetert de leesbaarheid en testbaarheid van de code.
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
// Lijnparameters
context.setStrokeColor(UIColor.darkGray.cgColor)
context.setLineWidth(2.0)
// Een driehoek tekenen
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()
}
In dit voorbeeld tekent draw(_:) een driehoek met een donkergrijze omtrek van 2 pixels dik. Het aanroepen van super.draw(rect) aan het begin van de methode wordt door Apple aanbevolen om de bovenliggende tekenlogica te behouden, hoewel de standaardimplementatie van draw(_:) in UIView leeg is.
Elke aanroep van draw(_:) moet bij dezelfde invoergegevens een identiek resultaat opleveren. Hierdoor kan het systeem het resultaat cachen en draw(_:) niet opnieuw aanroepen als de inhoud van de view niet is veranderd. Gebruik geen willekeurige waarden, systeemtijd of netwerkverzoeken binnen draw(_:).
drawRect: — historisch de eerste versie van de methode, verschenen in iOS 2.0 samen met Objective-C. In Swift werd de methode hernoemd naar draw(_:) met gebruik van de externe parameter _. Functioneel zijn de methodes identiek: beide ontvangen een CGRect van het te hertekenen gebied en gebruiken UIGraphicsGetCurrentContext() voor toegang tot de grafische context.
| Kenmerk | draw(_:) (Swift) | drawRect: (Objective-C) |
|---|---|---|
| Handtekening | override func draw(_ rect: CGRect) | - (void)drawRect:(CGRect)rect |
| Super-aanroep | super.draw(rect) | [super drawRect:rect] |
| Context | UIGraphicsGetCurrentContext() | UIGraphicsGetCurrentContext() |
| Parameter rect | rect: CGRect | CGRect rect |
| Prestaties | Identiek | Identiek |
Bij het migreren van een project van Objective-C naar Swift is het hernoemen van de methode een van de eerste taken. Xcode biedt een automatische converter, maar drawRect: vereist handmatige update naar draw(_:). Volgens Apple (2024) heeft de Swift-versie draw(_:) de voorkeur voor nieuwe projecten.
draw(_:) wordt op de CPU uitgevoerd en een niet-geoptimaliseerde implementatie kan leiden tot framedrops en lage prestaties. Apple beveelt verschillende bewezen benaderingen aan om het tekenen te versnellen.
Elke Core Graphics-bewerking (move(to:), addLine(to:), strokePath) heeft overhead. Groepeer bewerkingen en gebruik CGPath voor complexe vormen — het pad wordt eenmaal gemaakt en opnieuw gebruikt bij elke aanroep van draw(_:).
UIBezierPath — is een Objective-C-wrapper rond CGPath die een eenvoudige API biedt voor het maken van vormen. Maak UIBezierPath van tevoren (bijv. in de initialisator) en roep eenvoudig fill() of stroke() aan binnen draw(_:).
private let starPath: UIBezierPath = {
let path = UIBezierPath()
// Een stervorm maken
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()
}
Ontwikkelaars maken vaak dezelfde fouten bij het overschrijven van draw(_:). Kennis van deze patronen helpt bugs en prestatievermindering te voorkomen. Laten we de meest voorkomende problemen en hun oplossingen bekijken.
Door deze regels te volgen, zorgt u voor stabiel en snel tekenen van aangepaste views in elk iOS-project. Profileer draw(_:) via Instruments (Core Animation) om de werkelijke uitvoeringstijd en knelpunten te zien.
Veelgestelde vragen
Nee, directe aanroep van draw(_:) is verboden door de Apple-documentatie. Het systeem beheert zelf de tekencyclus. Gebruik setNeedsDisplay() om hertekenen aan te vragen, dat de view correct markeert als update-behoeftig in de dichtstbijzijnde rendercyclus.
Functioneel zijn deze methodes identiek. drawRect: wordt gebruikt in Objective-C, draw(_:) in Swift. Beide ontvangen een CGRect van het te hertekenen gebied en gebruiken dezelfde Core Graphics-context via UIGraphicsGetCurrentContext().
Apple optimaliseert rendering: als UIView geen overschreven draw(_:) heeft, maakt het systeem geen bitmapcontext voor de view aan. Dit bespaart geheugen. Als de overschrijving bestaat maar de methode niet wordt aangeroepen — controleer of het frame van de view niet nul is en de view zichtbaar is.
Alleen wanneer nodig: eerste rendering, na setNeedsDisplay(), bij wijzigen van bounds met contentMode = .redraw. In statische toestand wordt draw(_:) niet opnieuw aangeroepen, wat CPU- en batterijbronnen bespaart.
Apple raadt aan om super.draw(rect) aan te roepen aan het begin van de overschreven methode. Hoewel de huidige UIView-implementatie leeg is, zorgt de super-aanroep voor compatibiliteit met toekomstige versies van UIKit en is het een goede gewoonte.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook