setNeedsDisplay(): essentie van de methode en hertekeningsmechanisme in iOS

Auteur: IT Sectr Gepubliceerd: 2026-07-20 Leestijd: 6 min

setNeedsDisplay() — dit is een instantiemethode van UIView die een weergave markeert als opnieuw getekend moet worden. In tegenstelling tot een directe aanroep van draw(_:), stelt setNeedsDisplay() alleen een dirty-vlag in voor de weergave en geeft de controle onmiddellijk terug. Het systeem verwerkt dit verzoek in de dichtstbijzijnde rendercyclus, waardoor meerdere aanroepen kunnen worden samengevoegd in één tekenbewerking. Volgens Apple Documentation (2025) is uitgestelde hertekening via setNeedsDisplay() de enige correcte manier om de inhoud van een aangepaste UIView bij te werken.

Belangrijkste punten

  • setNeedsDisplay() — uitgesteld hertekeningsverzoek van UIView, roept draw(_:) niet synchroon aan
  • dirty flag — interne vlag van de weergave, ingesteld door setNeedsDisplay() en gereset na draw(_:)
  • setNeedsDisplay(_:) — overbelasting met CGRect voor gedeeltelijke hertekening van alleen het opgegeven gebied
  • displayIfNeeded() — gedwongen synchrone hertekening, gebruikt voor onmiddellijke bijwerking
  • Rendercyclus — het systeem verwerkt dirty-weergaven aan het einde van de run loop, waarbij meerdere verzoeken in één doorgang worden samengevoegd

Wat is setNeedsDisplay()

setNeedsDisplay() — is een UIView-methode die het systeem signaleert dat de inhoud van de weergave verouderd is en opnieuw gerenderd moet worden. De methode accepteert geen parameters en retourneert void. Na aanroep wordt de weergave gemarkeerd als dirty, en in de dichtstbijzijnde tekencyclus roept het systeem draw(_:) aan voor deze weergave.

Het belangrijkste kenmerk is asynchroniteit. Meerdere opeenvolgende aanroepen van setNeedsDisplay() voor dezelfde weergave leiden niet tot meerdere aanroepen van draw(_:) — het systeem voegt ze samen in één bewerking. Dit is cruciaal voor prestaties: als een eigenschap van de weergave meerdere keren per frame verandert, wordt draw(_:) slechts één keer aangeroepen.

Hoe werkt uitgestelde hertekening

Het mechanisme van uitgestelde hertekening is gebaseerd op de UIKit-rendercyclus. Wanneer setNeedsDisplay() wordt aangeroepen, stelt het systeem de interne vlag layer.needsDisplay in op true. Aan het einde van de huidige run loop doorloopt het systeem alle dirty-lagen en roept draw(_:) aan voor elke laag.

Run loop en renderstappen

De UIKit-run loop omvat de update-fase, waarin dirty-weergaven worden verwerkt. In deze fase wordt layoutSubviews() indien nodig aangeroepen, gevolgd door draw(_:) voor alle gemarkeerde weergaven. Na voltooiing van het tekenen wordt het resultaat via Core Animation naar de GPU gestuurd voor compositie.

swift
class ProgressView: UIView {
    var progress: CGFloat = 0 {
        didSet {
            setNeedsDisplay()
        }
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        guard let ctx = UIGraphicsGetCurrentContext() else { return }

        // Achtergrond
        ctx.setFillColor(UIColor.lightGray.cgColor)
        ctx.fill(rect)

        // Voortgangsbalk
        let fillRect = CGRect(x: rect.minX, y: rect.minY,
                              width: rect.width * progress, height: rect.height)
        ctx.setFillColor(UIColor.systemGreen.cgColor)
        ctx.fill(fillRect)
    }
}

In dit voorbeeld werkt progressView progress bij, en elke setter roept automatisch setNeedsDisplay() aan. Het systeem wacht op het einde van de run loop en roept draw(_:) aan met de huidige waarde van progress. Als progress drie keer per frame verandert, wordt draw(_:) slechts één keer uitgevoerd — met de laatste waarde.

setNeedsDisplay() vs setNeedsDisplay(_:)

De methode setNeedsDisplay(_:) accepteert een parameter rect van het type CGRect, die het hertekeningsgebied beperkt. Dit maakt het mogelijk om alleen het gewijzigde deel van de weergave opnieuw te tekenen, niet het geheel. Het prestatieverschil wordt merkbaar bij het werken met grote weergaven waar wijzigingen een klein gebied betreffen.

KenmerksetNeedsDisplay()setNeedsDisplay(_:)
ParameterGeenCGRect — hertekeningsgebied
HertekeningsgebiedGehele bounds van weergaveAlleen opgegeven rechthoek
PrestatiesLager bij grote weergavenHoger bij gedeeltelijke wijzigingen
Parameter rect in draw(_:)Gehele boundsOpgegeven rechthoek
Wanneer gebruikenWijziging van hele inhoudPuntsgewijze wijzigingen (cursor, highlight)

Voor complexe grafische afbeeldingen wordt aanbevolen eerst de hele scène in een offscreen-context te tekenen en vervolgens setNeedsDisplay(_:) alleen aan te roepen voor het gewijzigde gebied. Dit is een standaardtechniek in tekenapplicaties en grafische editors op iOS.

displayIfNeeded() versus setNeedsDisplay()

displayIfNeeded() — is een synchrone methode die onmiddellijk de hertekening start van alle dirty-weergaven in de hiërarchie, zonder te wachten op het einde van de run loop. In tegenstelling tot setNeedsDisplay(), die alleen een vlag instelt, dwingt displayIfNeeded() de onmiddellijke uitvoering van draw(_:) af.

Apple raadt aan displayIfNeeded() alleen in uiterste gevallen te gebruiken, wanneer het tekenresultaat onmiddellijk nodig is — bijvoorbeeld vóór het maken van een schermafbeelding of bij synchrone generatie van een afbeelding voor UIGraphicsImageRenderer. In normale scenario's heeft het asynchrone model via setNeedsDisplay() de voorkeur omdat het de hoofdthread niet blokkeert.

swift
    // Asynchroon — aanbevolen
someView.setNeedsDisplay()

    // Synchroon — alleen wanneer nodig
someView.setNeedsDisplay()
someView.displayIfNeeded() // draw(_:) onmiddellijk aangeroepen

Een aanroep van displayIfNeeded() zonder voorafgaand setNeedsDisplay() heeft geen effect — de methode verwerkt alleen weergaven die al als dirty zijn gemarkeerd. Als geen enkele weergave hertekening nodig heeft, wordt displayIfNeeded() beëindigd zonder draw(_:) aan te roepen.

Optimalisatie van setNeedsDisplay()-aanroepen

Frequente aanroepen van setNeedsDisplay() kunnen de prestaties verminderen, vooral tijdens animatie. Laten we de belangrijkste optimalisatiestrategieën bekijken.

Wijzigingen bundelen via model

Roep setNeedsDisplay() niet aan bij elke wijziging van een afzonderlijke eigenschap, maar verzamel wijzigingen en roep de methode één keer aan na het toepassen van alle updates. Bijvoorbeeld bij het wijzigen van kleur, grootte en positie van een element — roep setNeedsDisplay() één keer aan na het instellen van alle eigenschappen.

Gebruik CALayer voor animeerbare eigenschappen

Als een eigenschap kan worden geanimeerd via CALayer (backgroundColor, opacity, position, transform), gebruik dan Core Animation in plaats van draw(_:). CALayer-eigenschappen worden op de GPU bijgewerkt zonder draw(_:) aan te roepen, wat 60 FPS oplevert zonder CPU-belasting.

Batch-updates via CATransaction

Gebruik CATransaction om meerdere wijzigingen te groeperen in één renderdoorgang. Dit maakt het mogelijk meerdere setNeedsDisplay()-aanroepen samen te voegen in één draw(_:)-bewerking aan het einde van de transactie.

swift
CATransaction.begin()
CATransaction.setDisableActions(true)

view1.setNeedsDisplay()
view2.setNeedsDisplay()
view3.setNeedsDisplay()

CATransaction.commit()

Misbruik displayIfNeeded() niet — synchrone hertekening blokkeert de main-thread en kan frameverlies veroorzaken. Gebruik het alleen voor bewerkingen waarbij het tekenresultaat kritiek is vóór het einde van de huidige run loop.

Veelgestelde vragen

Kan draw(_:) direct worden aangeroepen in plaats van setNeedsDisplay()?

Nee, directe aanroep van draw(_:) is verboden. setNeedsDisplay() markeert de weergave correct als dirty, en het systeem roept draw(_:) aan op het juiste moment in de rendercyclus. Directe aanroep van draw(_:) negeert het caching-mechanisme en kan leiden tot inconsistente toestand.

Wat gebeurt er bij meerdere aanroepen van setNeedsDisplay()?

Meerdere aanroepen van setNeedsDisplay() voor dezelfde weergave worden door het systeem samengevoegd in één aanroep van draw(_:). Dit gebeurt omdat de methode alleen de dirty flag instelt, die pas wordt gereset na de daadwerkelijke uitvoering van draw(_:) aan het einde van de run loop.

Wat is het verschil tussen setNeedsDisplay() en setNeedsLayout()?

setNeedsDisplay() vraagt om hertekening van de weergave-inhoud (aanroep draw(_:)). setNeedsLayout() vraagt om herindeling van subviews (aanroep layoutSubviews()). layoutSubviews() kan leiden tot verandering van afmetingen, wat op zijn beurt hertekening kan veroorzaken.

Wanneer setNeedsDisplay(_:) gebruiken?

setNeedsDisplay(_:) moet worden gebruikt bij puntsgewijze wijzigingen: cursorverplaatsing, kleurverandering van geselecteerd gebied, bijwerken van een deel van een grafiek. Dit beperkt het hertekeningsgebied en verhoogt de prestaties in vergelijking met volledige hertekening van de hele weergave.

Zorgt een framewijziging automatisch voor setNeedsDisplay()?

Standaard veroorzaakt een wijziging van frame of bounds geen setNeedsDisplay(). Het systeem verplaatst alleen de weergave. Als hertekening nodig is bij groottewijziging, stel dan de eigenschap contentMode in op .redraw — dan roept UIKit automatisch setNeedsDisplay() aan bij elke verandering van bounds.

Samenvatting

  • setNeedsDisplay() — asynchrone UIView-methode voor het aanvragen van uitgestelde hertekening via het instellen van een dirty-vlag
  • setNeedsDisplay(_:) — overbelasting met CGRect voor gedeeltelijke hertekening van alleen het opgegeven gebied, optimaliseert prestaties
  • displayIfNeeded() — synchrone methode voor onmiddellijke hertekening van dirty-weergaven, alleen gebruikt bij uiterste noodzaak
  • Run loop — het systeem verwerkt dirty-weergaven aan het einde van de huidige cyclus en voegt meerdere aanroepen samen in één draw(_:)-doorgang
  • CALayer — voor animeerbare eigenschappen (position, opacity) gebruik Core Animation in plaats van draw(_:) — dit is aanzienlijk efficiënter
  • CATransaction — groepeert meerdere wijzigingen in één rendercyclus, waardoor het aantal draw(_:)-aanroepen vermindert
  • contentMode = .redraw — activeert automatische aanroep van setNeedsDisplay() bij wijziging van bounds van de weergave

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.

Bespreek het project

Lees ook