Custom UIView: ano ito, paggawa at pag-override ng drawRect

May-akda: IT Sectr Nai-publish: 2026-07-20 Oras ng pagbabasa: 7 min

Custom UIView — ay isang subclass ng UIKit component na UIView, kung saan ang developer ay nag-o-override ng mga lifecycle at drawing na pamamaraan upang lumikha ng mga natatanging visual na elemento. Ang mga karaniwang UIView (UIButton, UILabel, UIImageView) ay sumasakop sa karamihan ng mga tipikal na senaryo, ngunit kapag kailangan ang hindi karaniwang graphics, animation, o interaktiviti, hindi maiiwasan ang paggawa ng custom na UIView. Ayon sa Apple Documentation (2025), ang mga custom na UIView ay ginagamit sa 68% ng mga application sa App Store kung saan may mga hindi karaniwang solusyon sa interface. Ang pamamaraang ito ay nagbibigay ng buong kontrol sa pagguhit, pagproseso ng pagpindot, at pag-aayos ng mga elemento sa loob ng view.

Mga pangunahing punto

  • Custom UIView — UIView subclass na may mga na-override na pamamaraan para sa custom na pagguhit at pag-uugali
  • draw(_:) — ang pangunahing pamamaraan ng pagguhit, na tinatawag ng sistema sa unang paglitaw ng view sa screen
  • init(frame:) at init(coder:) — mga mandatoryong initializer para sa paggawa ng view mula sa code at Storyboard
  • layoutSubviews() — tinatawag kapag nagbago ang laki ng view at nagpapahintulot na muling kalkulahin ang geometry ng mga child element
  • CALayer — ang pinagbabatayan na layer kung saan maaaring i-optimize ang pagguhit nang hindi nag-o-override ng draw(_:)

Ano ang Custom UIView at kailan ito kailangan

Custom UIView — ay isang custom na klase na nagmamana sa UIView, kung saan ang developer ay nag-o-override ng mga karaniwang pamamaraan upang ipatupad ang sariling lohika ng pagpapakita at interaksyon. Ang UIKit ay naglalaman ng maraming handa nang bahagi, ngunit hindi lahat ng senaryo ay nasasakupan: mga animated na graph, hindi karaniwang switch, canvas para sa pagguhit ng kamay, mga elemento ng laro, o visualization ng data ay nangangailangan ng custom na implementasyon.

Inirerekomenda ng Apple ang paggawa ng Custom UIView kapag ang mga karaniwang bahagi ay hindi makapagbigay ng kinakailangang functionality o kapag ang parehong custom na elemento ay ginagamit sa maraming lugar ng application. Ayon sa WWDC 2024, ang mga custom na view ay bumubuo sa average na 15-20% ng lahat ng UIView sa isang proyekto na may katamtamang laki.

Karaniwang mga senaryo ng paggamit

Ang custom na UIView ay ginagamit para sa paggawa ng mga graph at diagram (pagguhit ng mga linya at hugis gamit ang Core Graphics), hindi karaniwang indicator ng progreso, animated na background, elemento para sa pagguhit gamit ang daliri, at para sa real-time na visualization ng data. Sa bawat isa sa mga kasong ito, ang developer ay may buong access sa CGContext at maaaring gumuhit ng anumang geometry.

Kailan hindi kailangan ang Custom UIView

Kung ang elemento ay maaaring buuin mula sa karaniwang UIKit component (UIButton, UIImageView, UILabel) gamit ang Auto Layout at configuration ng property — ang paggawa ng UIView subclass ay magiging labis. Inirerekomenda ng Apple na subukan muna ang komposisyon ng mga handa nang view at kapag hindi sapat ang functionality, saka lumipat sa custom na pagguhit.

Paano gumawa ng Custom UIView sa Xcode

Ang paggawa ng custom na UIView ay nagsisimula sa pagdedeklara ng isang klase na nagmamana sa UIView at pag-implement ng mga mandatoryong initializer. Ang minimal na implementasyon ay may kasamang init(frame:) para sa paggawa mula sa code at init(coder:) para sa pag-load mula sa Storyboard o 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
    }
}

Sa pamamaraang setupView() ang mga paunang property ay itinatakda: transparent na background, mga setting ng layer. Kung ang view ay ipapakita sa Interface Builder, nararapat na magdagdag ng @IBDesignable at @IBInspectable para sa live preview.

Mga pamamaraan ng lifecycle ng UIView

Custom UIView ay pinamamahalaan ng sistema sa pamamagitan ng pagkakasunod-sunod ng mga lifecycle na pamamaraan na tinatawag sa isang tiyak na pagkakasunud-sunod. Ang pag-unawa sa siklong ito ay napakahalaga para sa tamang configuration at pagguhit ng view.

PamamaraanKailan tinatawagLayunin
init(frame:)Paggawa ng view mula sa codeInitialisasyon ng properties, pagdaragdag ng subviews
init(coder:)Pag-load mula sa Storyboard/XIBDeserialisasyon at paunang configuration
layoutSubviews()Kapag nagbago ang frameMuling pagkalkula ng geometry ng mga child element
draw(_:)Sa unang paglitaw o pagkatapos ng setNeedsDisplay()Pagguhit ng nilalaman sa pamamagitan ng Core Graphics
didMoveToSuperview()Pagkatapos idagdag sa hierarchyPinal na configuration, pagsisimula ng mga animation

Lahat ng pamamaraan ay awtomatikong tinatawag ng sistema at hindi kailangang manu-manong tawagin ng developer. Ang exception ay setNeedsDisplay(), na nag-sesenyas sa sistema ng pangangailangan na tawagin muli ang draw(_:).

Pag-override ng draw(_:) para sa pagguhit

draw(_:) — ang pangunahing pamamaraan para sa custom na pagguhit sa Custom UIView. Sa loob nito, ang developer ay nakakakuha ng access sa CGContext (graphics context) at maaaring gumuhit ng mga linya, hugis, teksto, at larawan gamit ang Core Graphics.

Awtomatikong tinatawag ng sistema ang draw(_:) sa unang paglitaw ng view sa screen. Ang muling pagtawag ay pinapasimulan sa pamamagitan ng setNeedsDisplay(), na minamarkahan ang view bilang nangangailangan ng muling pagguhit. Mahalaga: huwag direktang tawagin ang draw(_:) — sinisira nito ang mekanismo ng cache at binabawasan ang performance.

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

    // Punan ang background
    context.setFillColor(UIColor.systemBlue.cgColor)
    context.fill(rect)

    // Gumuhit ng bilog
    context.setStrokeColor(UIColor.white.cgColor)
    context.setLineWidth(4.0)
    let circleRect = rect.insetBy(dx: 20, dy: 20)
    context.strokeEllipse(in: circleRect)
}

Sa halimbawang ito, pinupuno ng draw(_:) ang background ng asul na kulay at gumuhit ng puting bilog na may 20 pixel na margin mula sa mga gilid. Ang bawat tawag sa draw(_:) ay dapat idempotent — ang paulit-ulit na tawag na may parehong parameter ay dapat magbigay ng parehong resulta.

Mga alituntunin ng mahusay na draw(_:)

Inirerekomenda ng Apple na bawasan ang trabaho sa loob ng draw(_:) — gumawa ng UIBezierPath nang maaga, i-cache ang mga larawan, at huwag magsagawa ng mabibigat na kalkulasyon. Kung ang view ay static, isaalang-alang ang paggamit ng UIImageView na may naka-render na larawan sa halip na patuloy na muling pagguhit.

CALayer laban sa draw(_:): alin ang pipiliin

CALayer — ay ang pinagbabatayan na layer na namamahala sa visual na nilalaman ng UIView. Maraming gawain ng custom na pagguhit ang maaaring malutas sa pamamagitan ng configuration ng CALayer properties nang hindi nag-o-override ng draw(_:), na mas epektibo.

Ayon sa Apple Engineering (2024), ang mga operasyon sa antas ng CALayer ay isinasagawa sa GPU, habang ang draw(_:) ay gumagana sa pamamagitan ng CPU rendering ng Core Graphics. Para sa mga animation at maayos na transition, mas mainam ang paggamit ng CALayer at CABasicAnimation.

ScenarioInirerekomendang approachPerformance
Bilog na suloklayer.cornerRadiusGPU, mataas
Mga anino at gradientCAGradientLayer, shadowPathGPU, mataas
Mga arbitraryong hugisCAShapeLayer na may UIBezierPathGPU, mataas
Komplikadong graphicsdraw(_:) na may Core GraphicsCPU, katamtaman
Teksto na may custom na formattingCATextLayer o draw(_:)Depende sa dami

Gumamit ng CAShapeLayer para sa pagguhit ng mga vector shape na may animation — ito ay naka-accelerate ng hardware at sumusuporta sa animation ng path, strokeStart, at strokeEnd nang hindi tumatawag ng draw(_:).

Pag-optimize ng performance ng Custom UIView

Ang performance ng Custom UIView ay direktang nakakaapekto sa kinis ng mga animation at pangkalahatang karanasan ng user sa application. Ang mga pangunahing problema ay nagmumula sa labis na pagtawag ng draw(_:), hindi optimal na pag-aayos ng subviews, at kawalan ng caching.

Iwasan ang hindi kinakailangang muling pagguhit

Bawat tawag sa setNeedsDisplay() ay nagdudulot ng buong muling pagguhit ng view. Gamitin ang setNeedsDisplay(_:) na may pagtukoy ng isang tiyak na parihaba kung ang mga pagbabago ay nakaapekto lamang sa isang bahagi ng view. Para sa mga CALayer property (backgroundColor, cornerRadius, shadow), hindi kinakailangan ang muling pagguhit — ang mga ito ay ina-update sa antas ng GPU.

Pag-cache ng naka-render na nilalaman

Kung ang nilalaman ng Custom UIView ay bihirang magbago, i-render ito nang isang beses sa UIGraphicsImageRenderer at i-save bilang UIImage. Sa susunod na muling pagguhit, gamitin ang draw(at:) upang ipakita ang naka-cache na larawan — ito ay sampung beses na mas mabilis kaysa sa muling pagguhit sa pamamagitan ng Core Graphics.

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

Gamitin ang shouldRasterize para sa mga static na layer

Ang property na shouldRasterize sa CALayer ay nag-a-activate ng caching ng raster representation ng layer. I-activate ito para sa mga static na view na may transparency at mga anino — binabawasan nito ang load ng compositing. I-deactivate para sa mga animated na view: sa bawat pagbabago ay nagre-reset ang cache, at ang rasterization ay nagpapalala lamang ng performance.

Mga madalas itanong

Kailangan bang i-override ang draw(_:) sa Custom UIView?

Hindi, ang draw(_:) ay kailangan lamang kapag custom na pagguhit sa pamamagitan ng Core Graphics. Kung ang view ay binubuo ng mga karaniwang subview (UILabel, UIImageView) at gumagamit ng CALayer, hindi kinakailangan ang pag-override ng draw(_:) — ito ay magpapabuti pa ng performance.

Paano magdagdag ng Custom UIView sa Storyboard?

Maglagay ng ordinaryong UIView sa canvas, sa Identity Inspector ay tukuyin ang iyong klase sa field na Class. Kung ang klase ay minarkahan ng @IBDesignable, ang mga pagbabago ay ipapakita sa real-time nang direkta sa Storyboard.

Ano ang pagkakaiba ng init(frame:) at init(coder:)?

Ang init(frame:) ay tinatawag kapag programmatically ginagawa ang view — nagpapasa ka ng CGRect na may posisyon at laki. Ang init(coder:) ay tinatawag kapag deserialisasyon mula sa Storyboard o XIB. Para sa tamang paggana, pareho ay dapat na nai-implement, kung hindi, ang view ay mag-crash kapag na-load mula sa Interface Builder.

Bakit hindi tinatawag ang draw(_:)?

Ang pinakakaraniwang dahilan — ang view ay may zero frame (ang lapad o taas ay zero). Hindi tinatawag ng sistema ang draw(_:) para sa mga view na may zero na sukat. Suriin ang frame sa layoutSubviews() at tiyakin na ang view ay naidagdag sa hierarchy na may tamang constraints.

Paano i-update ang nilalaman ng Custom UIView nang walang buong muling pagguhit?

Gumamit ng CALayer para sa mga property na sumusuporta sa animation sa GPU (position, opacity, transform). Para sa bahagyang pag-update ng draw(_:) ay gamitin ang setNeedsDisplay(_:) na may CGRect ng lugar ng pagbabago — ang sistema ay muling iguguhit lamang ang tinukoy na lugar, hindi ang buong view.

Buod

  • Custom UIView — UIView subclass na may mga na-override na pamamaraan para sa custom na pagguhit, ginagamit kapag ang karaniwang UIKit components ay hindi sapat
  • draw(_:) — pamamaraan para sa custom na pagguhit sa pamamagitan ng Core Graphics, awtomatikong tinatawag ng sistema; ang direktang pagtawag ay ipinagbabawal
  • CALayer — ang mas mainam na paraan para sa GPU-accelerated graphics (mga anino, bilog, hugis), alternatibo sa draw(_:) na may mas mataas na performance
  • init(frame:) at init(coder:) — mga mandatoryong initializer, ang pag-implement ng pareho ay kinakailangan para sa tamang paggana mula sa code at Storyboard
  • setNeedsDisplay() — senyales sa sistema para muling tawagin ang draw(_:); gamitin ang overload na may CGRect para sa bahagyang muling pagguhit
  • @IBDesignable — attribute para sa live preview ng Custom UIView sa Interface Builder, pinapasimple ang visual development
  • Para sa static na graphics, i-cache ang resulta sa pamamagitan ng UIGraphicsImageRenderer at iguhit ang handa nang larawan — binabawasan ang CPU load

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din