setNeedsDisplay(): Wesen der Methode und Neuzeichnungsmechanismus in iOS

Autor: IT Sectr Veröffentlicht: 2026-07-20 Lesezeit: 6 Min.

setNeedsDisplay() ist eine Instanzmethode von UIView, die die View als neuzeichnungsbedürftig markiert. Im Gegensatz zum direkten Aufruf von draw(_:) setzt setNeedsDisplay() nur das dirty-Flag für die View und gibt sofort die Kontrolle zurück. Das System verarbeitet diese Anforderung im nächsten Renderzyklus, wodurch mehrere Aufrufe zu einem einzigen Zeichenvorgang zusammengefasst werden können. Laut Apple Documentation (2025) ist das verzögerte Neuzeichnen über setNeedsDisplay() die einzig korrekte Methode, um den Inhalt einer benutzerdefinierten UIView zu aktualisieren.

Wichtigste Erkenntnisse

  • setNeedsDisplay() — eine verzögerte Neuzeichnungsanforderung für UIView, ruft draw(_:) nicht synchron auf
  • dirty-Flag — ein internes View-Flag, das von setNeedsDisplay() gesetzt und nach draw(_:) zurückgesetzt wird
  • setNeedsDisplay(_:) — eine Überladung mit CGRect für teilweises Neuzeichnen nur des angegebenen Bereichs
  • displayIfNeeded() — erzwungenes synchrones Neuzeichnen, für sofortige Aktualisierungen verwendet
  • Renderzyklus — das System verarbeitet dirty-Views am Ende des Run Loops und fasst mehrere Anforderungen in einem Durchlauf zusammen

Was ist setNeedsDisplay()

setNeedsDisplay() ist eine UIView-Methode, die dem System signalisiert, dass der Inhalt der View veraltet ist und neu gerendert werden muss. Die Methode nimmt keine Parameter entgegen und gibt void zurück. Nach dem Aufruf wird die View als dirty markiert, und im nächsten Zeichenzyklus ruft das System draw(_:) für diese View auf.

Das Hauptmerkmal ist die Asynchronität. Mehrere aufeinanderfolgende Aufrufe von setNeedsDisplay() für dieselbe View führen nicht zu mehrfachen draw(_:)-Aufrufen — das System fasst sie zu einem einzigen Vorgang zusammen. Dies ist für die Leistung von entscheidender Bedeutung: Wenn sich eine View-Eigenschaft mehrmals pro Frame ändert, wird draw(_:) nur einmal aufgerufen.

Wie funktioniert das verzögerte Neuzeichnen

Der Mechanismus des verzögerten Neuzeichnens basiert auf dem UIKit-Renderzyklus. Wenn setNeedsDisplay() aufgerufen wird, setzt das System das interne Flag layer.needsDisplay auf true. Am Ende des aktuellen Run Loops durchläuft das System alle dirty-Layer und ruft für jeden draw(_:) auf.

Run Loop und Render-Schritte

Der UIKit-Run-Loop enthält eine Update-Phase, in der dirty-Views verarbeitet werden. In dieser Phase wird bei Bedarf layoutSubviews() aufgerufen, dann draw(_:) für alle markierten Views. Nach Abschluss der Zeichnung wird das Ergebnis über Core Animation zur Compositing an die GPU übergeben.

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

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

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

        // Fortschrittsbalken
        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 diesem Beispiel aktualisiert progressView progress, und jeder Setter ruft automatisch setNeedsDisplay() auf. Das System wartet das Ende des Run Loops ab und ruft draw(_:) mit dem tatsächlichen progress-Wert auf. Wenn sich progress dreimal pro Frame ändert, wird draw(_:) nur einmal ausgeführt — mit dem letzten Wert.

setNeedsDisplay() vs setNeedsDisplay(_:)

Die Methode setNeedsDisplay(_:) nimmt einen rect-Parameter vom Typ CGRect entgegen, der den Neuzeichnungsbereich begrenzt. Dadurch kann nur der geänderte Teil der View neu gezeichnet werden, anstatt der gesamten View. Der Leistungsunterschied wird bei großen Views deutlich, bei denen Änderungen einen kleinen Bereich betreffen.

EigenschaftsetNeedsDisplay()setNeedsDisplay(_:)
ParameterKeinerCGRect — Neuzeichnungsbereich
NeuzeichnungsbereichGesamte View-BoundsNur das angegebene Rechteck
LeistungNiedriger bei großen ViewsHöher bei teilweisen Änderungen
rect-Parameter in draw(_:)Gesamte BoundsAngegebenes Rechteck
VerwendungÄnderung des gesamten InhaltsPunktuelle Änderungen (Cursor, Hervorhebung)

Für komplexe Grafiken wird empfohlen, die gesamte Szene zuerst in einem Offscreen-Kontext zu zeichnen und dann setNeedsDisplay(_:) nur für den geänderten Bereich aufzurufen. Dies ist eine Standardtechnik in Zeichenanwendungen und Grafikeditoren unter iOS.

displayIfNeeded() gegen setNeedsDisplay()

displayIfNeeded() ist eine synchrone Methode, die sofort das Neuzeichnen aller dirty-Views in der Hierarchie auslöst, ohne auf das Ende des Run Loops zu warten. Im Gegensatz zu setNeedsDisplay(), das nur ein Flag setzt, erzwingt displayIfNeeded() die sofortige Ausführung von draw(_:).

Apple empfiehlt, displayIfNeeded() nur in extremen Fällen zu verwenden, wenn das Zeichenergebnis sofort benötigt wird — zum Beispiel vor dem Erstellen eines Screenshots oder bei der synchronen Bildgenerierung für UIGraphicsImageRenderer. In normalen Szenarien ist das asynchrone Modell über setNeedsDisplay() vorzuziehen, da es den Hauptthread nicht blockiert.

swift
    // Asynchron — empfohlen
someView.setNeedsDisplay()

    // Synchron — nur bei Bedarf
someView.setNeedsDisplay()
someView.displayIfNeeded() // draw(_:) sofort aufgerufen

Ein Aufruf von displayIfNeeded() ohne vorheriges setNeedsDisplay() hat keine Wirkung — die Methode verarbeitet nur bereits als dirty markierte Views. Wenn keine View neu gezeichnet werden muss, wird displayIfNeeded() ohne Aufruf von draw(_:) abgeschlossen.

Optimierung von setNeedsDisplay()-Aufrufen

Häufige setNeedsDisplay()-Aufrufe können die Leistung beeinträchtigen, insbesondere bei Animationen. Betrachten wir die wichtigsten Optimierungsstrategien.

Bündelung von Änderungen über ein Modell

Anstatt setNeedsDisplay() bei jeder Änderung einer einzelnen Eigenschaft aufzurufen, sammeln Sie Änderungen und rufen Sie die Methode einmal nach Anwendung aller Aktualisierungen auf. Wenn Sie beispielsweise Farbe, Größe und Position eines Elements ändern — rufen Sie setNeedsDisplay() einmal nach dem Setzen aller Eigenschaften auf.

Verwendung von CALayer für animierbare Eigenschaften

Wenn eine Eigenschaft über CALayer (backgroundColor, opacity, position, transform) animiert werden kann, verwenden Sie Core Animation anstelle von draw(_:). CALayer-Eigenschaften werden auf der GPU ohne Aufruf von draw(_:) aktualisiert und bieten 60 FPS ohne CPU-Belastung.

Batch-Update über CATransaction

Um mehrere Änderungen in einem einzigen Renderdurchlauf zu gruppieren, verwenden Sie CATransaction. Dies ermöglicht die Zusammenfassung mehrerer setNeedsDisplay()-Aufrufe zu einem einzigen draw(_:)-Vorgang am Ende der Transaktion.

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

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

CATransaction.commit()

Verwenden Sie displayIfNeeded() nicht übermäßig — synchrones Neuzeichnen blockiert den Hauptthread und kann zu Bildaussetzern führen. Verwenden Sie es nur für Vorgänge, bei denen das Zeichenergebnis vor Ende des aktuellen Run Loops kritisch ist.

Häufig gestellte Fragen

Kann ich draw(_:) direkt anstelle von setNeedsDisplay() aufrufen?

Nein, der direkte Aufruf von draw(_:) ist verboten. setNeedsDisplay() markiert die View korrekt als dirty, und das System ruft draw(_:) zum richtigen Zeitpunkt des Renderzyklus auf. Der direkte Aufruf von draw(_:) ignoriert den Caching-Mechanismus und kann zu einem inkonsistenten Zustand führen.

Was passiert bei mehrfachen Aufrufen von setNeedsDisplay()?

Mehrere Aufrufe von setNeedsDisplay() für dieselbe View werden vom System zu einem einzigen draw(_:)-Aufruf zusammengefasst. Dies geschieht, weil die Methode nur das dirty-Flag setzt, das erst nach der tatsächlichen Ausführung von draw(_:) am Ende des Run Loops zurückgesetzt wird.

Wie unterscheidet sich setNeedsDisplay() von setNeedsLayout()?

setNeedsDisplay() fordert ein Neuzeichnen des View-Inhalts an (Aufruf von draw(_:)). setNeedsLayout() fordert eine Neuanordnung der Subviews an (Aufruf von layoutSubviews()). layoutSubviews() kann zu Größenänderungen führen, die wiederum ein Neuzeichnen auslösen können.

Wann sollte setNeedsDisplay(_:) verwendet werden?

setNeedsDisplay(_:) sollte für punktuelle Änderungen verwendet werden: Cursorbewegung, Farbänderung eines ausgewählten Bereichs, Aktualisierung eines Teils eines Diagramms. Dies begrenzt den Neuzeichnungsbereich und verbessert die Leistung im Vergleich zum Neuzeichnen der gesamten View.

Ruft eine Änderung des frame automatisch setNeedsDisplay() auf?

Standardmäßig löst eine Änderung von frame oder bounds kein setNeedsDisplay() aus. Das System verschiebt die View nur. Wenn bei Größenänderungen ein Neuzeichnen erforderlich ist, setzen Sie die Eigenschaft contentMode auf .redraw — dann ruft UIKit bei jeder bounds-Änderung automatisch setNeedsDisplay() auf.

Zusammenfassung

  • setNeedsDisplay() — eine asynchrone UIView-Methode zur Anforderung verzögerten Neuzeichnens durch Setzen des dirty-Flags
  • setNeedsDisplay(_:) — eine Überladung mit CGRect für teilweises Neuzeichnen nur des angegebenen Bereichs, optimiert die Leistung
  • displayIfNeeded() — eine synchrone Methode zum sofortigen Neuzeichnen von dirty-Views, nur bei absoluter Notwendigkeit verwendet
  • Run Loop — das System verarbeitet dirty-Views am Ende des aktuellen Zyklus und fasst mehrere Aufrufe in einem draw(_:)-Durchlauf zusammen
  • CALayer — für animierbare Eigenschaften (position, opacity) verwenden Sie Core Animation statt draw(_:) — das ist um Größenordnungen effizienter
  • CATransaction — fasst mehrere Änderungen in einem Renderzyklus zusammen und reduziert die Anzahl der draw(_:)-Aufrufe
  • contentMode = .redraw — aktiviert den automatischen setNeedsDisplay()-Aufruf bei Änderung der View-Bounds

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch