Custom UIView ist eine Unterklasse der UIKit-Komponente UIView, in der der Entwickler Lebenszyklus- und Zeichenmethoden überschreibt, um einzigartige visuelle Elemente zu erstellen. Standard-UIViews (UIButton, UILabel, UIImageView) decken die meisten typischen Szenarien ab, aber wenn nicht standardmäßige Grafiken, Animationen oder Interaktivität erforderlich sind, ist die Erstellung einer benutzerdefinierten UIView unerlässlich. Laut Apple Documentation (2025) werden benutzerdefinierte UIViews in 68% der App Store-Anwendungen verwendet, die nicht standardmäßige Oberflächenlösungen aufweisen. Dieser Ansatz bietet vollständige Kontrolle über das Zeichnen, die Touch-Verarbeitung und das Layout der Elemente innerhalb der Ansicht.
Wichtige Punkte
Custom UIView ist eine benutzerdefinierte Klasse, die von UIView erbt, in der der Entwickler Standardmethoden überschreibt, um benutzerdefinierte Anzeige- und Interaktionslogik zu implementieren. UIKit enthält viele integrierte Komponenten, aber sie decken nicht alle Szenarien ab: animierte Diagramme, benutzerdefinierte Schalter, Freihandzeichenfläche, Spielelemente oder Datenvisualisierung erfordern eine benutzerdefinierte Implementierung.
Apple empfiehlt die Erstellung einer Custom UIView, wenn Standardkomponenten die erforderliche Funktionalität nicht bereitstellen können oder wenn dasselbe benutzerdefinierte Element an mehreren Stellen der Anwendung verwendet wird. Laut WWDC 2024 machen benutzerdefinierte Ansichten in einem mittelgroßen Projekt durchschnittlich 15-20% aller UIViews aus.
Custom UIView wird zum Erstellen von Diagrammen und Grafiken (Zeichnen von Linien und Formen mit Core Graphics), benutzerdefinierten Fortschrittsanzeigen, animierten Hintergründen, Fingerzeichenelementen und Echtzeit-Datenvisualisierung verwendet. In jedem dieser Fälle erhält der Entwickler vollständigen Zugriff auf CGContext und kann jede Geometrie zeichnen.
Wenn ein Element aus Standard-UIKit-Komponenten (UIButton, UIImageView, UILabel) mit Auto Layout und Eigenschaftskonfiguration zusammengesetzt werden kann, ist die Erstellung einer UIView-Unterklasse übertrieben. Apple empfiehlt, zuerst die Komposition vorgefertigter Ansichten zu versuchen und nur bei unzureichender Funktionalität auf benutzerdefiniertes Zeichnen umzusteigen.
Die Erstellung einer benutzerdefinierten UIView beginnt mit der Deklaration einer Klasse, die von UIView erbt, und der Implementierung der erforderlichen Initialisierer. Die minimale Implementierung umfasst init(frame:) zum Erstellen aus Code und init(coder:) zum Laden aus Storyboard oder XIB.
import UIKit
class CircleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
private func setupView() {
backgroundColor = .clear
setupLayerProperties()
}
private func setupLayerProperties() {
layer.cornerRadius = bounds.width / 2
layer.masksToBounds = true
}
}
In der setupView()-Methode werden Anfangseigenschaften festgelegt: transparenter Hintergrund, Layer-Einstellungen. Wenn die Ansicht im Interface Builder angezeigt wird, lohnt es sich, @IBDesignable und @IBInspectable für die Live-Vorschau hinzuzufügen.
Custom UIView wird vom System durch eine Sequenz von Lebenszyklusmethoden verwaltet, die in einer bestimmten Reihenfolge aufgerufen werden. Das Verständnis dieses Zyklus ist für die korrekte Einrichtung und das Zeichnen der Ansicht von entscheidender Bedeutung.
| Methode | Wann aufgerufen | Zweck |
|---|---|---|
| init(frame:) | Erstellen der Ansicht aus Code | Initialisierung von Eigenschaften, Hinzufügen von Unteransichten |
| init(coder:) | Laden aus Storyboard/XIB | Deserialisierung und Anfangseinrichtung |
| layoutSubviews() | Bei Änderung des Rahmens | Neuberechnung der Geometrie von Unterelementen |
| draw(_:) | Beim ersten Erscheinen oder nach setNeedsDisplay() | Zeichnen des Inhalts über Core Graphics |
| didMoveToSuperview() | Nach dem Hinzufügen zur Hierarchie | Endgültige Einrichtung, Starten von Animationen |
Alle Methoden werden automatisch vom System aufgerufen, und der Entwickler muss sie nicht manuell aufrufen. Die Ausnahme ist setNeedsDisplay(), das dem System signalisiert, draw(_:) erneut aufzurufen.
draw(_:) ist die Schlüsselmethode für benutzerdefiniertes Zeichnen in Custom UIView. In ihr erhält der Entwickler Zugriff auf CGContext (Grafikkontext) und kann Linien, Formen, Text und Bilder mit Core Graphics zeichnen.
Das System ruft draw(_:) automatisch auf, wenn die Ansicht zum ersten Mal auf dem Bildschirm erscheint. Ein nachfolgender Aufruf wird durch setNeedsDisplay() ausgelöst, das die Ansicht als neu zu zeichnen markiert. Wichtig: Rufen Sie draw(_:) nicht direkt auf — dies zerstört den Caching-Mechanismus und verringert die Leistung.
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
// Hintergrundfüllung
context.setFillColor(UIColor.systemBlue.cgColor)
context.fill(rect)
// Einen Kreis zeichnen
context.setStrokeColor(UIColor.white.cgColor)
context.setLineWidth(4.0)
let circleRect = rect.insetBy(dx: 20, dy: 20)
context.strokeEllipse(in: circleRect)
}
In diesem Beispiel füllt draw(_:) den Hintergrund mit blauer Farbe und zeichnet einen weißen Kreis mit einem Abstand von 20 Pixeln von den Rändern. Jeder Aufruf von draw(_:) sollte idempotent sein — mehrere Aufrufe mit denselben Parametern sollten dasselbe Ergebnis liefern.
Apple empfiehlt, die Arbeit innerhalb von draw(_:) zu minimieren — erstellen Sie UIBezierPath im Voraus, cachen Sie Bilder und führen Sie keine schweren Berechnungen durch. Wenn die Ansicht statisch ist, erwägen Sie die Verwendung von UIImageView mit einem gerenderten Bild anstelle ständigen Neuzeichnens.
CALayer ist die zugrunde liegende Ebene, die den visuellen Inhalt von UIView verwaltet. Viele benutzerdefinierte Zeichenaufgaben können durch Konfigurieren von CALayer-Eigenschaften ohne Überschreiben von draw(_:) gelöst werden, was wesentlich effizienter ist.
Laut Apple Engineering (2024) werden Operationen auf CALayer-Ebene auf der GPU ausgeführt, während draw(_:) über CPU-basiertes Core Graphics Rendering arbeitet. Für Animationen und flüssige Übergänge ist die Verwendung von CALayer und CABasicAnimation vorzuziehen.
| Szenario | Empfohlener Ansatz | Leistung |
|---|---|---|
| Abgerundete Ecken | layer.cornerRadius | GPU, hoch |
| Schatten und Verläufe | CAGradientLayer, shadowPath | GPU, hoch |
| Beliebige Formen | CAShapeLayer mit UIBezierPath | GPU, hoch |
| Komplexe Grafiken | draw(_:) mit Core Graphics | CPU, mittel |
| Text mit benutzerdefinierter Formatierung | CATextLayer oder draw(_:) | Abhängig vom Umfang |
Verwenden Sie CAShapeLayer zum Zeichnen von Vektorformen mit Animation — es ist hardwarebeschleunigt und unterstützt Pfad-, strokeStart- und strokeEnd-Animation ohne Aufruf von draw(_:).
Die Leistung von Custom UIView wirkt sich direkt auf die Flüssigkeit von Animationen und das allgemeine Benutzererlebnis aus. Hauptprobleme entstehen durch übermäßige draw(_:)-Aufrufe, suboptimales Layout von Unteransichten und fehlendes Caching.
Jeder Aufruf von setNeedsDisplay() löst ein vollständiges Neuzeichnen der Ansicht aus. Verwenden Sie setNeedsDisplay(_:) mit einem bestimmten Rechteck, wenn Änderungen nur einen Teil der Ansicht betroffen haben. Für CALayer-Eigenschaften (backgroundColor, cornerRadius, shadow) ist kein Neuzeichnen erforderlich — sie werden auf GPU-Ebene aktualisiert.
Wenn sich der Inhalt von Custom UIView selten ändert, rendern Sie ihn einmal in UIGraphicsImageRenderer und speichern Sie ihn als UIImage. Verwenden Sie beim nächsten Neuzeichnen draw(at:), um das gecachte Bild anzuzeigen — das ist dutzende Male schneller als erneutes Rendern über Core Graphics.
func renderToImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
return renderer.image { ctx in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
Die shouldRasterize-Eigenschaft von CALayer aktiviert das Caching der Rasterdarstellung der Ebene. Aktivieren Sie sie für statische Ansichten mit Transparenz und Schatten — dies reduziert die Compositing-Last. Deaktivieren Sie sie für animierte Ansichten: Der Cache wird bei jeder Änderung zurückgesetzt, und die Rasterung verschlechtert nur die Leistung.
Häufig gestellte Fragen
Nein, draw(_:) wird nur für benutzerdefiniertes Zeichnen über Core Graphics benötigt. Wenn die Ansicht aus Standard-Unteransichten (UILabel, UIImageView) besteht und CALayer verwendet, ist das Überschreiben von draw(_:) nicht erforderlich — es verbessert sogar die Leistung.
Platzieren Sie eine normale UIView auf der Leinwand, geben Sie im Identity Inspector Ihre Klasse im Feld Class an. Wenn die Klasse mit @IBDesignable markiert ist, werden Änderungen in Echtzeit direkt im Storyboard angezeigt.
init(frame:) wird beim programmatischen Erstellen der Ansicht aufgerufen — Sie übergeben ein CGRect mit Position und Größe. init(coder:) wird beim Deserialisieren aus Storyboard oder XIB aufgerufen. Für den korrekten Betrieb müssen beide implementiert werden, andernfalls stürzt Ihre Ansicht beim Laden aus dem Interface Builder ab.
Der häufigste Grund ist, dass die Ansicht einen Null-Rahmen hat (Breite oder Höhe gleich Null). Das System ruft draw(_:) nicht für Ansichten mit Null-Abmessungen auf. Überprüfen Sie den Rahmen in layoutSubviews() und stellen Sie sicher, dass die Ansicht mit korrekten Constraints zur Hierarchie hinzugefügt wurde.
Verwenden Sie CALayer für Eigenschaften, die GPU-Animation unterstützen (position, opacity, transform). Für teilweise Aktualisierungen von draw(_:) verwenden Sie setNeedsDisplay(_:) mit einem CGRect des geänderten Bereichs — das System zeichnet nur die angegebene Region neu, nicht die gesamte Ansicht.
Zusammenfassung
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.
Lesen Sie auch