Custom UIView — is een subklasse van het UIKit-component UIView, waarin de ontwikkelaar methoden van de levenscyclus en het tekenen overschrijft om unieke visuele elementen te creëren. Standaard UIView's (UIButton, UILabel, UIImageView) dekken de meeste typische scenario's, maar wanneer aangepaste graphics, animatie of interactiviteit nodig is, kan het niet zonder het maken van een aangepaste UIView. Volgens Apple Documentation (2025) worden aangepaste UIView's gebruikt in 68% van de App Store-applicaties waar niet-standaard interface-oplossingen voorkomen. Deze benadering geeft volledige controle over het tekenen, de verwerking van aanrakingen en de plaatsing van elementen binnen de weergave.
Belangrijkste punten
Custom UIView — is een aangepaste klasse die overerft van UIView, waarin de ontwikkelaar standaardmethoden overschrijft om eigen weergave- en interactielogica te implementeren. UIKit bevat veel kant-en-klare componenten, maar ze dekken niet alle scenario's: geanimeerde grafieken, aangepaste schakelaars, canvas om met de hand te tekenen, game-elementen of gegevensvisualisatie vereisen een aangepaste implementatie.
Apple raadt aan een Custom UIView te maken wanneer standaardcomponenten de benodigde functionaliteit niet kunnen bieden of wanneer hetzelfde aangepaste element op meerdere plaatsen in de applicatie wordt gebruikt. Volgens WWDC 2024 vormen aangepaste views gemiddeld 15-20% van alle UIView's in een middelgroot project.
Aangepaste UIView wordt gebruikt voor het bouwen van grafieken en diagrammen (tekenen van lijnen en vormen met Core Graphics), aangepaste voortgangsindicatoren, geanimeerde achtergronden, elementen om met de vinger te tekenen, en voor real-time gegevensvisualisatie. In elk van deze gevallen krijgt de ontwikkelaar volledige toegang tot CGContext en kan elke geometrie tekenen.
Als het element kan worden samengesteld uit standaard UIKit-componenten (UIButton, UIImageView, UILabel) met behulp van Auto Layout en eigenschapsconfiguratie — dan is het maken van een UIView-subklasse overbodig. Apple raadt aan eerst compositie van kant-en-klare views te proberen en alleen wanneer de functionaliteit ontoereikend is, over te stappen op aangepast tekenen.
Het maken van een aangepaste UIView begint met het declareren van een klasse die overerft van UIView en het implementeren van de verplichte initializers. De minimale implementatie omvat init(frame:) voor het maken vanuit code en init(coder:) voor het laden vanuit Storyboard of 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 de methode setupView() worden initiële eigenschappen ingesteld: transparante achtergrond, laaginstellingen. Als de view in Interface Builder wordt weergegeven, is het de moeite waard om @IBDesignable en @IBInspectable toe te voegen voor live preview.
Custom UIView wordt door het systeem beheerd via een reeks levenscyclusmethoden die in een bepaalde volgorde worden aangeroepen. Inzicht in deze cyclus is cruciaal voor een correcte configuratie en weergave van de view.
| Methode | Wanneer aangeroepen | Doel |
|---|---|---|
| init(frame:) | View maken vanuit code | Initialisatie van eigenschappen, toevoegen van subviews |
| init(coder:) | Laden vanuit Storyboard/XIB | Deserialisatie en initiële configuratie |
| layoutSubviews() | Bij wijziging van het frame | Herberekenen van de geometrie van onderliggende elementen |
| draw(_:) | Bij eerste weergave of na setNeedsDisplay() | Inhoud tekenen via Core Graphics |
| didMoveToSuperview() | Na toevoeging aan de hiërarchie | Definitieve configuratie, starten van animaties |
Alle methoden worden automatisch door het systeem aangeroepen en de ontwikkelaar hoeft ze niet handmatig aan te roepen. Uitzondering — setNeedsDisplay(), die het systeem signaleert dat draw(_:) opnieuw moet worden aangeroepen.
draw(_:) — de belangrijkste methode voor aangepast tekenen in Custom UIView. Binnenin krijgt de ontwikkelaar toegang tot CGContext (de grafische context) en kan lijnen, vormen, tekst en afbeeldingen tekenen met Core Graphics.
Het systeem roept draw(_:) automatisch aan bij de eerste weergave van de view op het scherm. Een hernieuwde aanroep wordt geïnitieerd via setNeedsDisplay(), die de view markeert als opnieuw moet worden getekend. Belangrijk: roep draw(_:) niet direct aan — dit verbreekt het cachemechanisme en vermindert de prestaties.
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
// Achtergrond vullen
context.setFillColor(UIColor.systemBlue.cgColor)
context.fill(rect)
// Cirkel tekenen
context.setStrokeColor(UIColor.white.cgColor)
context.setLineWidth(4.0)
let circleRect = rect.insetBy(dx: 20, dy: 20)
context.strokeEllipse(in: circleRect)
}
In dit voorbeeld vult draw(_:) de achtergrond met blauwe kleur en tekent een witte cirkel met een marge van 20 pixels van de randen. Elke aanroep van draw(_:) moet idempotent zijn — herhaalde aanroep met dezelfde parameters moet hetzelfde resultaat geven.
Apple raadt aan het werk binnen draw(_:) te minimaliseren — maak UIBezierPath van tevoren, cache afbeeldingen en voer geen zware berekeningen uit. Als de view statisch is, overweeg dan het gebruik van UIImageView met een gerenderde afbeelding in plaats van constant opnieuw tekenen.
CALayer — is de onderliggende laag die de visuele inhoud van UIView beheert. Veel taken van aangepast tekenen kunnen worden opgelost door het configureren van CALayer-eigenschappen zonder draw(_:) te overschrijven, wat aanzienlijk efficiënter is.
Volgens Apple Engineering (2024) worden bewerkingen op CALayer-niveau uitgevoerd op de GPU, terwijl draw(_:) werkt via CPU-rendering van Core Graphics. Voor animaties en vloeiende overgangen heeft het gebruik van CALayer en CABasicAnimation de voorkeur.
| Scenario | Aanbevolen aanpak | Prestaties |
|---|---|---|
| Afgeronde hoeken | layer.cornerRadius | GPU, hoog |
| Schaduwen en gradiënten | CAGradientLayer, shadowPath | GPU, hoog |
| Willekeurige vormen | CAShapeLayer met UIBezierPath | GPU, hoog |
| Complexe graphics | draw(_:) met Core Graphics | CPU, gemiddeld |
| Tekst met aangepaste opmaak | CATextLayer of draw(_:) | Afhankelijk van omvang |
Gebruik CAShapeLayer voor het tekenen van vectorvormen met animatie — het is hardware-versneld en ondersteunt animatie van path, strokeStart en strokeEnd zonder draw(_:) aan te roepen.
De prestaties van Custom UIView hebben direct invloed op de vloeiendheid van animaties en de algemene gebruikerservaring van de applicatie. De belangrijkste problemen ontstaan door overmatige aanroepen van draw(_:), suboptimale plaatsing van subviews en het ontbreken van caching.
Elke aanroep van setNeedsDisplay() leidt tot volledig opnieuw tekenen van de view. Gebruik setNeedsDisplay(_:) met specificatie van een specifieke rechthoek als de wijzigingen slechts een deel van de view hebben getroffen. Voor CALayer-eigenschappen (backgroundColor, cornerRadius, shadow) is opnieuw tekenen niet nodig — ze worden op GPU-niveau bijgewerkt.
Als de inhoud van Custom UIView zelden verandert, render deze dan eenmalig in UIGraphicsImageRenderer en sla op als UIImage. Gebruik bij het volgende opnieuw tekenen draw(at:) om de gecachte afbeelding weer te geven — dit is tientallen keren sneller dan opnieuw tekenen via Core Graphics.
func renderToImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
return renderer.image { ctx in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
De eigenschap shouldRasterize van CALayer schakelt het cachen van de gerasterde weergave van de laag in. Schakel het in voor statische views met transparantie en schaduwen — dit vermindert de compositielast. Schakel het uit voor geanimeerde views: bij elke wijziging wordt de cache gereset en verslechtert rasterisatie alleen de prestaties.
Veelgestelde vragen
Nee, draw(_:) is alleen nodig bij aangepast tekenen via Core Graphics. Als de view is samengesteld uit standaard subviews (UILabel, UIImageView) en CALayer gebruikt, is het overschrijven van draw(_:) niet vereist — dit verbetert zelfs de prestaties.
Plaats een gewone UIView op het canvas, geef in de Identity Inspector uw klasse op in het veld Class. Als de klasse is gemarkeerd met @IBDesignable, worden wijzigingen in realtime direct in Storyboard weergegeven.
init(frame:) wordt aangeroepen bij het programmatisch maken van de view — u geeft een CGRect met positie en grootte door. init(coder:) wordt aangeroepen bij deserialisatie uit Storyboard of XIB. Voor correcte werking moeten beide zijn geïmplementeerd, anders crasht de view bij het laden vanuit Interface Builder.
De meest voorkomende oorzaak — de view heeft een nul-frame (breedte of hoogte is nul). Het systeem roept draw(_:) niet aan voor views met nul-afmetingen. Controleer het frame in layoutSubviews() en zorg ervoor dat de view met correcte constraints aan de hiërarchie is toegevoegd.
Gebruik CALayer voor eigenschappen die animatie op de GPU ondersteunen (position, opacity, transform). Gebruik voor gedeeltelijke update van draw(_:) setNeedsDisplay(_:) met de CGRect van het wijzigingsgebied — het systeem tekent alleen het opgegeven gebied opnieuw, niet de hele view.
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