Custom UIView — är en underklass av UIKit-komponenten UIView, där utvecklaren överskrider livscykel- och ritmetoder för att skapa unika visuella element. Standard UIView (UIButton, UILabel, UIImageView) täcker de flesta typiska scenarier, men när icke-standard grafik, animation eller interaktivitet krävs, går det inte utan att skapa en anpassad UIView. Enligt Apple Documentation (2025) används anpassade UIView i 68% av App Store-applikationer där icke-standardiserade gränssnittslösningar förekommer. Detta tillvägagångssätt ger full kontroll över ritning, bearbetning av beröringar och placering av element inuti vyn.
Huvudpunkter
Custom UIView — är en anpassad klass som ärver från UIView, där utvecklaren överskrider standardmetoder för att implementera egen visnings- och interaktionslogik. UIKit innehåller många färdiga komponenter, men de täcker inte alla scenarier: animerade diagram, icke-standardiserade växlar, canvas för handritning, spelelement eller datavisualisering kräver anpassad implementering.
Apple rekommenderar att skapa Custom UIView när standardkomponenter inte kan tillhandahålla nödvändig funktionalitet eller när samma anpassade element används på flera ställen i applikationen. Enligt WWDC 2024 utgör anpassade vyer i genomsnitt 15-20% av alla UIView i ett medelstort projekt.
Anpassad UIView används för att bygga diagram och grafer (ritning av linjer och former med Core Graphics), anpassade förloppsindikatorer, animerade bakgrunder, element för fingerritning, samt för datavisualisering i realtid. I vart och ett av dessa fall har utvecklaren full tillgång till CGContext och kan rita vilken geometri som helst.
Om elementet kan sättas ihop från standard UIKit-komponenter (UIButton, UIImageView, UILabel) med hjälp av Auto Layout och egenskapskonfiguration — då är det överflödigt att skapa en UIView-underklass. Apple rekommenderar att först prova komposition av färdiga vyer och endast när funktionaliteten är otillräcklig, gå över till anpassad ritning.
Skapandet av en anpassad UIView börjar med att deklarera en klass som ärver från UIView och implementera de obligatoriska initierarna. Den minimala implementeringen inkluderar init(frame:) för att skapa från kod och init(coder:) för att ladda från Storyboard eller 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
}
}
I metoden setupView() ställs initiala egenskaper in: transparent bakgrund, lagerinställningar. Om vyn kommer att visas i Interface Builder, är det värt att lägga till @IBDesignable och @IBInspectable för live-förhandsvisning.
Custom UIView hanteras av systemet genom en sekvens av livscykelmetoder som anropas i en viss ordning. Att förstå denna cykel är avgörande för korrekt konfiguration och ritning av vyn.
| Metod | När den anropas | Syfte |
|---|---|---|
| init(frame:) | Skapa vy från kod | Initiera egenskaper, lägga till subviews |
| init(coder:) | Ladda från Storyboard/XIB | Deserialisering och initial konfiguration |
| layoutSubviews() | När ramen ändras | Beräkna om geometrin för underordnade element |
| draw(_:) | Vid första visningen eller efter setNeedsDisplay() | Rita innehåll via Core Graphics |
| didMoveToSuperview() | Efter tillägg i hierarkin | Slutlig konfiguration, starta animationer |
Alla metoder anropas automatiskt av systemet och utvecklaren behöver inte anropa dem manuellt. Undantag — setNeedsDisplay(), som signalerar systemet att draw(_:) behöver anropas igen.
draw(_:) — nyckelmetoden för anpassad ritning i Custom UIView. Inuti den får utvecklaren tillgång till CGContext (grafiskt sammanhang) och kan rita linjer, former, text och bilder med Core Graphics.
Systemet anropar draw(_:) automatiskt när vyn först visas på skärmen. Återanrop initieras genom setNeedsDisplay(), som markerar vyn som behövande omritning. Viktigt: anropa inte draw(_:) direkt — det förstör cachningsmekanismen och minskar prestanda.
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
// Fylla bakgrund
context.setFillColor(UIColor.systemBlue.cgColor)
context.fill(rect)
// Rita cirkel
context.setStrokeColor(UIColor.white.cgColor)
context.setLineWidth(4.0)
let circleRect = rect.insetBy(dx: 20, dy: 20)
context.strokeEllipse(in: circleRect)
}
I detta exempel fyller draw(_:) bakgrunden med blå färg och ritar en vit cirkel med 20 pixlars marginal från kanterna. Varje anrop av draw(_:) bör vara idempotent — upprepat anrop med samma parametrar bör ge samma resultat.
Apple rekommenderar att minimera arbetet inuti draw(_:) — skapa UIBezierPath i förväg, cacha bilder och utför inte tunga beräkningar. Om vyn är statisk, överväg att använda UIImageView med en renderad bild istället för konstant omritning.
CALayer — är det underliggande lagret som hanterar UIView:s visuella innehåll. Många uppgifter inom anpassad ritning kan lösas genom att konfigurera CALayer-egenskaper utan att överskriva draw(_:), vilket är avsevärt effektivare.
Enligt Apple Engineering (2024) utförs operationer på CALayer-nivå på GPU, medan draw(_:) fungerar genom CPU-rendering av Core Graphics. För animationer och mjuka övergångar är användning av CALayer och CABasicAnimation att föredra.
| Scenario | Rekommenderad metod | Prestanda |
|---|---|---|
| Rundade hörn | layer.cornerRadius | GPU, hög |
| Skuggor och gradienter | CAGradientLayer, shadowPath | GPU, hög |
| Godtyckliga former | CAShapeLayer med UIBezierPath | GPU, hög |
| Komplex grafik | draw(_:) med Core Graphics | CPU, medel |
| Text med anpassad formatering | CATextLayer eller draw(_:) | Beror på volym |
Använd CAShapeLayer för att rita vektorformer med animation — den är hårdvaruaccelererad och stöder animation av path, strokeStart och strokeEnd utan att anropa draw(_:).
Prestandan hos Custom UIView påverkar direkt smidigheten i animationer och den övergripande användarupplevelsen av applikationen. Huvudproblemen uppstår på grund av överdrivna anrop av draw(_:), icke-optimal placering av subviews och brist på cachning.
Varje anrop av setNeedsDisplay() leder till fullständig omritning av vyn. Använd setNeedsDisplay(_:) med angivande av en specifik rektangel om ändringarna bara har påverkat en del av vyn. För CALayer-egenskaper (backgroundColor, cornerRadius, shadow) krävs ingen omritning — de uppdateras på GPU-nivå.
Om innehållet i Custom UIView sällan ändras, rendera det en gång i UIGraphicsImageRenderer och spara som UIImage. Vid nästa omritning, använd draw(at:) för att visa den cachade bilden — detta är tiotals gånger snabbare än omritning via Core Graphics.
func renderToImage() -> UIImage {
let renderer = UIGraphicsImageRenderer(size: bounds.size)
return renderer.image { ctx in
drawHierarchy(in: bounds, afterScreenUpdates: true)
}
}
Egenskapen shouldRasterize hos CALayer aktiverar cachning av lagerets rastrerade representation. Aktivera den för statiska vyer med transparens och skuggor — det minskar kompositbelastningen. Inaktivera för animerade vyer: vid varje ändring återställs cachen och rastrering försämrar bara prestandan.
Vanliga frågor
Nej, draw(_:) behövs bara vid anpassad ritning via Core Graphics. Om vyn består av standard subviews (UILabel, UIImageView) och använder CALayer, krävs inte överskrivning av draw(_:) — detta kommer till och med förbättra prestandan.
Placera en vanlig UIView på arbetsytan, i Identity Inspector ange din klass i fältet Class. Om klassen är markerad med @IBDesignable visas ändringarna i realtid direkt i Storyboard.
init(frame:) anropas vid programmatisk skapande av vyn — du skickar en CGRect med position och storlek. init(coder:) anropas vid deserialisering från Storyboard eller XIB. För korrekt funktion måste båda implementeras, annars kraschar vyn vid laddning från Interface Builder.
Den vanligaste orsaken — vyn har noll-ram (bredd eller höjd är noll). Systemet anropar inte draw(_:) för vyer med noll dimensioner. Kontrollera ramen i layoutSubviews() och se till att vyn har lagts till i hierarkin med korrekta begränsningar.
Använd CALayer för egenskaper som stöder animation på GPU (position, opacity, transform). För partiell uppdatering av draw(_:) använd setNeedsDisplay(_:) med CGRect för ändringsområdet — systemet ritar bara om det angivna området, inte hela vyn.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också