Custom UIView: τι είναι, δημιουργία και παράκαμψη του drawRect

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-07-20 Χρόνος ανάγνωσης: 7 λεπ

Custom UIView — είναι μια υποκλάση του στοιχείου UIKit UIView, στην οποία ο προγραμματιστής παρακάμπτει μεθόδους του κύκλου ζωής και της σχεδίασης για τη δημιουργία μοναδικών οπτικών στοιχείων. Τα τυπικά UIView (UIButton, UILabel, UIImageView) καλύπτουν τα περισσότερα τυπικά σενάρια, αλλά όταν απαιτείται μη τυπικά γραφικά, κινούμενα σχέδια ή διαδραστικότητα, δεν γίνεται χωρίς τη δημιουργία ενός προσαρμοσμένου UIView. Σύμφωνα με το Apple Documentation (2025), τα προσαρμοσμένα UIView χρησιμοποιούνται στο 68% των εφαρμογών του App Store όπου υπάρχουν μη τυπικές λύσεις διεπαφής. Αυτή η προσέγγιση παρέχει πλήρη έλεγχο στη σχεδίαση, την επεξεργασία αφής και τη διάταξη των στοιχείων μέσα στην προβολή.

Βασικά σημεία

  • Custom UIView — υποκλάση UIView με παρακαμφθείσες μεθόδους για προσαρμοσμένη σχεδίαση και συμπεριφορά
  • draw(_:) — η κύρια μέθοδος σχεδίασης, που καλείται από το σύστημα κατά την πρώτη εμφάνιση της προβολής στην οθόνη
  • init(frame:) και init(coder:) — υποχρεωτικοί αρχικοποιητές για τη δημιουργία προβολής από κώδικα και Storyboard
  • layoutSubviews() — καλείται όταν αλλάζουν οι διαστάσεις της προβολής και επιτρέπει τον επανυπολογισμό της γεωμετρίας των θυγατρικών στοιχείων
  • CALayer — το υποκείμενο επίπεδο μέσω του οποίου μπορεί να βελτιστοποιηθεί η σχεδίαση χωρίς παράκαμψη του draw(_:)

Τι είναι το Custom UIView και πότε χρειάζεται

Custom UIView — είναι μια προσαρμοσμένη κλάση που κληρονομεί από το UIView, στην οποία ο προγραμματιστής παρακάμπτει τις τυπικές μεθόδους για να υλοποιήσει τη δική του λογική εμφάνισης και αλληλεπίδρασης. Το UIKit περιέχει πολλά έτοιμα στοιχεία, αλλά δεν καλύπτουν όλα τα σενάρια: κινούμενα γραφήματα, μη τυπικούς διακόπτες, καμβά για σχέδιο με το χέρι, στοιχεία παιχνιδιού ή οπτικοποίηση δεδομένων απαιτούν προσαρμοσμένη υλοποίηση.

Η Apple συνιστά τη δημιουργία Custom UIView όταν τα τυπικά στοιχεία δεν μπορούν να παρέχουν την απαραίτητη λειτουργικότητα ή όταν το ίδιο προσαρμοσμένο στοιχείο χρησιμοποιείται σε πολλά σημεία της εφαρμογής. Σύμφωνα με το WWDC 2024, οι προσαρμοσμένες προβολές αποτελούν κατά μέσο όρο το 15-20% όλων των UIView σε ένα έργο μεσαίου μεγέθους.

Τυπικά σενάρια χρήσης

Το προσαρμοσμένο UIView χρησιμοποιείται για την κατασκευή γραφημάτων και διαγραμμάτων (σχεδίαση γραμμών και σχημάτων με Core Graphics), μη τυπικών δεικτών προόδου, κινούμενων φόντων, στοιχείων για σχέδιο με το δάχτυλο, καθώς και για οπτικοποίηση δεδομένων σε πραγματικό χρόνο. Σε κάθε μία από αυτές τις περιπτώσεις, ο προγραμματιστής έχει πλήρη πρόσβαση στο CGContext και μπορεί να σχεδιάσει οποιαδήποτε γεωμετρία.

Πότε δεν χρειάζεται Custom UIView

Εάν το στοιχείο μπορεί να συναρμολογηθεί από τυπικά στοιχεία UIKit (UIButton, UIImageView, UILabel) χρησιμοποιώντας Auto Layout και ρύθμιση ιδιοτήτων — η δημιουργία υποκλάσης UIView θα είναι περιττή. Η Apple συνιστά να δοκιμάζετε πρώτα τη σύνθεση έτοιμων προβολών και μόνο όταν η λειτουργικότητα είναι ανεπαρκής να προχωράτε στην προσαρμοσμένη σχεδίαση.

Πώς να δημιουργήσετε Custom UIView στο Xcode

Η δημιουργία ενός προσαρμοσμένου UIView ξεκινά με τη δήλωση μιας κλάσης που κληρονομεί από UIView και την υλοποίηση των υποχρεωτικών αρχικοποιητών. Η ελάχιστη υλοποίηση περιλαμβάνει init(frame:) για δημιουργία από κώδικα και init(coder:) για φόρτωση από Storyboard ή XIB.

swift
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
    }
}

Στη μέθοδο setupView() ορίζονται οι αρχικές ιδιότητες: διαφανές φόντο, ρυθμίσεις επιπέδου. Εάν η προβολή θα εμφανίζεται στο Interface Builder, αξίζει να προστεθούν @IBDesignable και @IBInspectable για ζωντανή προεπισκόπηση.

Μέθοδοι κύκλου ζωής UIView

Custom UIView διαχειρίζεται από το σύστημα μέσω μιας ακολουθίας μεθόδων κύκλου ζωής που καλούνται με συγκεκριμένη σειρά. Η κατανόηση αυτού του κύκλου είναι ζωτικής σημασίας για τη σωστή ρύθμιση και σχεδίαση της προβολής.

ΜέθοδοςΠότε καλείταιΣκοπός
init(frame:)Δημιουργία προβολής από κώδικαΑρχικοποίηση ιδιοτήτων, προσθήκη υποπροβολών
init(coder:)Φόρτωση από Storyboard/XIBΑποσειριοποίηση και αρχική ρύθμιση
layoutSubviews()Κατά την αλλαγή πλαισίουΕπανυπολογισμός γεωμετρίας θυγατρικών στοιχείων
draw(_:)Κατά την πρώτη εμφάνιση ή μετά από setNeedsDisplay()Σχεδίαση περιεχομένου μέσω Core Graphics
didMoveToSuperview()Μετά την προσθήκη στην ιεραρχίαΤελική ρύθμιση, έναρξη κινούμενων σχεδίων

Όλες οι μέθοδοι καλούνται αυτόματα από το σύστημα και ο προγραμματιστής δεν χρειάζεται να τις καλέσει χειροκίνητα. Εξαίρεση — setNeedsDisplay(), το οποίο σηματοδοτεί στο σύστημα την ανάγκη εκ νέου κλήσης του draw(_:).

Παράκαμψη του draw(_:) για σχεδίαση

draw(_:) — η βασική μέθοδος για προσαρμοσμένη σχεδίαση στο Custom UIView. Μέσα σε αυτήν, ο προγραμματιστής αποκτά πρόσβαση στο CGContext (γραφικό περιβάλλον) και μπορεί να σχεδιάσει γραμμές, σχήματα, κείμενο και εικόνες χρησιμοποιώντας το Core Graphics.

Το σύστημα καλεί το draw(_:) αυτόματα κατά την πρώτη εμφάνιση της προβολής στην οθόνη. Η εκ νέου κλήση πραγματοποιείται μέσω setNeedsDisplay(), το οποίο επισημαίνει την προβολή ως χρήζουσα επανασχεδίασης. Σημαντικό: μην καλείτε το draw(_:) απευθείας — αυτό χαλάει τον μηχανισμό προσωρινής αποθήκευσης και μειώνει την απόδοση.

swift
override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext() else { return }

    // Γέμισμα φόντου
    context.setFillColor(UIColor.systemBlue.cgColor)
    context.fill(rect)

    // Σχεδίαση κύκλου
    context.setStrokeColor(UIColor.white.cgColor)
    context.setLineWidth(4.0)
    let circleRect = rect.insetBy(dx: 20, dy: 20)
    context.strokeEllipse(in: circleRect)
}

Σε αυτό το παράδειγμα, το draw(_:) γεμίζει το φόντο με μπλε χρώμα και σχεδιάζει έναν λευκό κύκλο με περιθώριο 20 pixel από τις άκρες. Κάθε κλήση του draw(_:) πρέπει να είναι απαθής (idempotent) — η επαναλαμβανόμενη κλήση με τις ίδιες παραμέτρους πρέπει να δίνει το ίδιο αποτέλεσμα.

Κανόνες αποδοτικού draw(_:)

Η Apple συνιστά την ελαχιστοποίηση της εργασίας εντός του draw(_:) — δημιουργήστε UIBezierPath εκ των προτέρων, αποθηκεύστε προσωρινά εικόνες και μην εκτελείτε βαριούς υπολογισμούς. Εάν η προβολή είναι στατική, εξετάστε το ενδεχόμενο χρήσης UIImageView με απόδοση εικόνας αντί για συνεχή επανασχεδίαση.

CALayer έναντι draw(_:): τι να επιλέξετε

CALayer — είναι το υποκείμενο επίπεδο που διαχειρίζεται το οπτικό περιεχόμενο του UIView. Πολλές εργασίες προσαρμοσμένης σχεδίασης μπορούν να επιλυθούν μέσω ρύθμισης ιδιοτήτων CALayer χωρίς παράκαμψη του draw(_:), το οποίο είναι σημαντικά πιο αποδοτικό.

Σύμφωνα με το Apple Engineering (2024), οι λειτουργίες σε επίπεδο CALayer εκτελούνται στο GPU, ενώ το draw(_:) λειτουργεί μέσω απόδοσης CPU του Core Graphics. Για κινούμενα σχέδια και ομαλές μεταβάσεις, προτιμάται η χρήση του CALayer και του CABasicAnimation.

ΣενάριοΠροτεινόμενη προσέγγισηΑπόδοση
Στρογγυλεμένες γωνίεςlayer.cornerRadiusGPU, υψηλή
Σκιές και διαβαθμίσειςCAGradientLayer, shadowPathGPU, υψηλή
Αυθαίρετα σχήματαCAShapeLayer με UIBezierPathGPU, υψηλή
Πολύπλοκα γραφικάdraw(_:) με Core GraphicsCPU, μεσαία
Κείμενο με προσαρμοσμένη μορφοποίησηCATextLayer ή draw(_:)Εξαρτάται από τον όγκο

Χρησιμοποιήστε CAShapeLayer για σχεδίαση διανυσματικών σχημάτων με κινούμενα σχέδια — είναι επιταχυνόμενο από το υλικό και υποστηρίζει κινούμενα σχέδια path, strokeStart και strokeEnd χωρίς κλήση του draw(_:).

Βελτιστοποίηση απόδοσης Custom UIView

Η απόδοση του Custom UIView επηρεάζει άμεσα την ομαλότητα των κινούμενων σχεδίων και τη συνολική εμπειρία χρήστη της εφαρμογής. Τα κύρια προβλήματα προκύπτουν από υπερβολικές κλήσεις του draw(_:), μη βέλτιστη διάταξη υποπροβολών και έλλειψη προσωρινής αποθήκευσης.

Αποφύγετε τις περιττές επανασχεδιάσεις

Κάθε κλήση setNeedsDisplay() οδηγεί σε πλήρη επανασχεδίαση της προβολής. Χρησιμοποιήστε setNeedsDisplay(_:) με καθορισμό ενός συγκεκριμένου ορθογωνίου, εάν οι αλλαγές επηρέασαν μόνο ένα μέρος της προβολής. Για ιδιότητες CALayer (backgroundColor, cornerRadius, shadow) δεν απαιτείται επανασχεδίαση — ενημερώνονται σε επίπεδο GPU.

Προσωρινή αποθήκευση αποδοθέντος περιεχομένου

Εάν το περιεχόμενο του Custom UIView αλλάζει σπάνια, αποδώστε το μία φορά στο UIGraphicsImageRenderer και αποθηκεύστε το ως UIImage. Στην επόμενη επανασχεδίαση, χρησιμοποιήστε draw(at:) για εμφάνιση της προσωρινά αποθηκευμένης εικόνας — αυτό είναι δεκάδες φορές ταχύτερο από την εκ νέου σχεδίαση μέσω Core Graphics.

swift
func renderToImage() -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: bounds.size)
    return renderer.image { ctx in
        drawHierarchy(in: bounds, afterScreenUpdates: true)
    }
}

Χρησιμοποιήστε το shouldRasterize για στατικά επίπεδα

Η ιδιότητα shouldRasterize στο CALayer ενεργοποιεί την προσωρινή αποθήκευση της ψηφιοποιημένης αναπαράστασης του επιπέδου. Ενεργοποιήστε το για στατικές προβολές με διαφάνεια και σκιές — μειώνει το φορτίο σύνθεσης. Απενεργοποιήστε το για κινούμενες προβολές: με κάθε αλλαγή η προσωρινή μνήμη επαναφέρεται και η ψηφιοποίηση μόνο χειροτερεύει την απόδοση.

Συχνές ερωτήσεις

Είναι υποχρεωτική η παράκαμψη του draw(_:) στο Custom UIView;

Όχι, το draw(_:) χρειάζεται μόνο για προσαρμοσμένη σχεδίαση μέσω Core Graphics. Εάν η προβολή αποτελείται από τυπικές υποπροβολές (UILabel, UIImageView) και χρησιμοποιεί CALayer, η παράκαμψη του draw(_:) δεν απαιτείται — αυτό θα βελτιώσει μάλιστα την απόδοση.

Πώς να προσθέσετε Custom UIView στο Storyboard;

Τοποθετήστε ένα συνηθισμένο UIView στον καμβά, στο Identity Inspector καθορίστε την κλάση σας στο πεδίο Class. Εάν η κλάση φέρει την ένδειξη @IBDesignable, οι αλλαγές θα εμφανίζονται σε πραγματικό χρόνο απευθείας στο Storyboard.

Ποια είναι η διαφορά μεταξύ init(frame:) και init(coder:);

Το init(frame:) καλείται κατά τον προγραμματισμό δημιουργίας της προβολής — μεταφέρετε ένα CGRect με θέση και μέγεθος. Το init(coder:) καλείται κατά την αποσειριοποίηση από Storyboard ή XIB. Για σωστή λειτουργία, και τα δύο πρέπει να υλοποιηθούν, διαφορετικά η προβολή θα καταρρεύσει κατά τη φόρτωση από το Interface Builder.

Γιατί δεν καλείται το draw(_:);

Η συχνότερη αιτία — η προβολή έχει μηδενικό πλαίσιο (πλάτος ή ύψος ίσο με μηδέν). Το σύστημα δεν καλεί το draw(_:) για προβολές με μηδενικές διαστάσεις. Ελέγξτε το πλαίσιο στο layoutSubviews() και βεβαιωθείτε ότι η προβολή έχει προστεθεί στην ιεραρχία με σωστούς περιορισμούς.

Πώς να ενημερώσετε το περιεχόμενο του Custom UIView χωρίς πλήρη επανασχεδίαση;

Χρησιμοποιήστε CALayer για ιδιότητες που υποστηρίζουν κινούμενα σχέδια στο GPU (position, opacity, transform). Για μερική ενημέρωση του draw(_:) εφαρμόστε setNeedsDisplay(_:) με CGRect της περιοχής αλλαγής — το σύστημα θα επανασχεδιάσει μόνο την καθορισμένη περιοχή, όχι ολόκληρη την προβολή.

Σύνοψη

  • Custom UIView — υποκλάση UIView με παρακαμφθείσες μεθόδους για προσαρμοσμένη σχεδίαση, χρησιμοποιείται όταν τα τυπικά στοιχεία UIKit δεν επαρκούν
  • draw(_:) — μέθοδος για προσαρμοσμένη σχεδίαση μέσω Core Graphics, καλείται αυτόματα από το σύστημα· η απευθείας κλήση απαγορεύεται
  • CALayer — η προτιμώμενη μέθοδος για γραφικά επιταχυνόμενα από GPU (σκιές, στρογγυλεύσεις, σχήματα), εναλλακτική του draw(_:) με υψηλότερη απόδοση
  • init(frame:) και init(coder:) — υποχρεωτικοί αρχικοποιητές, η υλοποίηση και των δύο είναι απαραίτητη για σωστή λειτουργία από κώδικα και Storyboard
  • setNeedsDisplay() — σήμα στο σύστημα για εκ νέου κλήση του draw(_:)· χρησιμοποιήστε την υπερφόρτωση με CGRect για μερική επανασχεδίαση
  • @IBDesignable — χαρακτηριστικό για ζωντανή προεπισκόπηση του Custom UIView στο Interface Builder, απλοποιεί την οπτική ανάπτυξη
  • Για στατικά γραφικά αποθηκεύστε προσωρινά το αποτέλεσμα μέσω UIGraphicsImageRenderer και σχεδιάστε την έτοιμη εικόνα — μειώνει το φορτίο CPU

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης