draw(_:) və drawRect — bu nədir, çağırış və yenidən təyin etmə

Müəllif: IT Sectr Dərc olunub: 2026-07-20 Oxuma vaxtı: 7 dəq

draw(_:) / drawRect — bu UIView sinifinin (Swift-də) və onun Objective-C-dəki (drawRect:) analoqu olan, Core Graphics istifadə edərək görünüş məzmununun çəkilməsinə cavabdeh olan metoddur. Sistem bu metodu görünüş ekranda ilk dəfə görünəndə və setNeedsDisplay() çağırıldıqdan sonra avtomatik çağırır. Apple Documentation (2025) məlumatına görə, draw(_:) proqramçının xüsusi çəkmə üçün cari ekranın qrafik kontekstinə çıxışı olan yeganə metoddur. draw(_:)-i yenidən təyin etmək komponentin görünüşü üzərində tam nəzarət verir — sadə həndəsi fiqurlardan mürəkkəb animasiyalı qrafikə qədər.

Əsas məqamlar

  • draw(_:) — Core Graphics vasitəsilə xüsusi çəkmə üçün UIView metodu, proqramçı tərəfindən birbaşa çağırılmır
  • drawRect: — Objective-C-də draw(_:)-in ekvivalenti, sintaktik fərqlənir, funksional olaraq eynidir
  • CGContext — bütün çəkmə əməliyyatları üçün draw(_:) daxilində mövcud olan qrafik kontekst
  • setNeedsDisplay() — proqramçı tərəfindən draw(_:)-in təkrar çağırılmasını tələb etməyin yeganə düzgün yolu
  • UIGraphicsGetCurrentContext() — draw(_:) daxilində cari konteksti əldə etmək funksiyası, çəkmədən əvvəl məcburi addım

draw(_:) / drawRect nədir

draw(_:) — UIKit-in görünüş məzmununu render etmək üçün çağırdığı UIView nümunə metodudur. Bu metodun daxilində proqramçı CGContext qrafik kontekstinə çıxış əldə edir və xətlər, doldurmalar, mətn və şəkillər çəkmək üçün Core Graphics API-dən istifadə edir. Objective-C-də drawRect: eyni funksiyanı yerinə yetirir, lakin fərqli sintaksislə: yeganə parametr yenidən çəkiləcək sahəni təyin edən CGRect-dir.

Apple Engineering (2024) məlumatına görə, draw(_:) CPU renderinqi Bitmap Graphics Context vasitəsilə işləyir ki, bu da maksimum elastikliyi təmin edir, lakin CALayer ilə müqayisədə daha çox resurs tələb edir. draw(_:) istifadəsi barədə qərar qrafikin mürəkkəbliyinə və performans tələblərinə əsasən qəbul edilir.

Swift və Objective-C-də metodun imzası

Swift-də metod override func draw(_ rect: CGRect) kimi elan edilir, burada rect yenidən çəkilməsi tələb olunan düzbucaqlıdır. Objective-C-də imza - (void)drawRect:(CGRect)rect-dir. rect parametri setNeedsDisplay(_:) vasitəsilə qismən yenidən çəkmə zamanı görünüşün bounds-dən kiçik ola bilər.

objective-c
- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
    CGContextFillRect(context, rect);
}

Sistem draw(_:)-i nə vaxt çağırır

Sistem draw(_:)-i ciddi müəyyən edilmiş ssenarilərdə avtomatik çağırır. Bu tetikleyicileri anlamaq lazımsız yenidən çəkmələrdən qaçmağa və görünüş performansını optimallaşdırmağa kömək edir. Aşağıda metodun avtomatik çağırılmasının bütün halları verilmişdir.

  • İlk renderinq — görünüş ilk dəfə iyerarxiyaya əlavə edildikdə və ekranda görünəndə
  • setNeedsDisplay() — bu metod çağırıldıqdan sonra sistem tərəfindən ən yaxın çəkmə dövründə
  • setNeedsDisplay(_:) — eyni, lakin yenidən çəkmək üçün konkret düzbucaqlı göstərilməklə
  • contentMode — bounds dəyişdikdə, əgər contentMode yenidən çəkmə tələb edirsə (məsələn, .redraw)
  • setNeedsLayout() — bəzi hallarda subview-ların yenidən yerləşdirilməsindən sonra yenidən çəkmə tələb oluna bilər

Apple sənədləri xəbərdarlıq edir: heç vaxt draw(_:)-i birbaşa çağırmayın. Sistem özü çəkmənin nə vaxt yerinə yetiriləcəyinə qərar verir və birbaşa çağırış daxili keşləmə mexanizmini pozur. Yenidən çəkmə tələb etmək üçün həmişə setNeedsDisplay() və ya setNeedsDisplay(_:) istifadə edin.

Swift-də draw(_:)-i necə yenidən təyin etmək olar

Swift-də draw(_:)-i yenidən təyin etmək qrafik kontekstin əldə edilməsi və ardınca Core Graphics çağırışları ilə başlayır. Çəkmənin məntiqi blokları üçün ayrıca metodlar yaratmaq tövsiyə olunur — bu kodun oxunaqlılığını və test edilə bilməsini yaxşılaşdırır.

swift
override func draw(_ rect: CGRect) {
    super.draw(rect)

    guard let context = UIGraphicsGetCurrentContext() else { return }

    // Xətt parametrləri
    context.setStrokeColor(UIColor.darkGray.cgColor)
    context.setLineWidth(2.0)

    // Üçbucaq çəkmək
    context.move(to: CGPoint(x: rect.midX, y: rect.minY + 10))
    context.addLine(to: CGPoint(x: rect.maxX - 10, y: rect.maxY - 10))
    context.addLine(to: CGPoint(x: rect.minX + 10, y: rect.maxY - 10))
    context.closePath()
    context.strokePath()
}

Bu nümunədə draw(_:) 2 piksel qalınlığında tünd boz kontur ilə üçbucaq çəkir. Metodun əvvəlində super.draw(rect) çağırışı Apple tərəfindən valideyn çəkmə məntiqini qorumaq üçün tövsiyə olunur, baxmayaraq ki, UIView-də draw(_:)-in standart implementasiyası boşdur.

draw(_:)-in idempotentlik qaydası

draw(_:)-in hər çağırışı eyni giriş məlumatları ilə eyni nəticə verməlidir. Bu, sistemə nəticəni keşləməyə və görünüş məzmunu dəyişməyibsə, draw(_:)-i təkrar çağırmamağa imkan verir. draw(_:) daxilində təsadüfi dəyərlər, sistem vaxtı və ya şəbəkə sorğuları istifadə etməyin.

Objective-C-də drawRect: və draw(_:) ilə fərqi

drawRect: — tarixən iOS 2.0 ilə Objective-C ilə birlikdə ortaya çıxan metodun ilk variantıdır. Swift-də metod xarici parametr _ istifadə edərək draw(_:) adlandırıldı. Funksional olaraq metodlar eynidir: hər ikisi yenidən çəkmə sahəsinin CGRect-ni alır və qrafik kontekstə çıxış üçün UIGraphicsGetCurrentContext() istifadə edir.

Xüsusiyyətdraw(_:) (Swift)drawRect: (Objective-C)
İmzaoverride func draw(_ rect: CGRect)- (void)drawRect:(CGRect)rect
Super çağırışısuper.draw(rect)[super drawRect:rect]
KontekstUIGraphicsGetCurrentContext()UIGraphicsGetCurrentContext()
Parametr rectrect: CGRectCGRect rect
PerformansEyniEyni

Layihəni Objective-C-dən Swift-ə miqrasiya edərkən metodun adlandırılması ilk vəzifələrdən biridir. Xcode avtomatik çevirici təqdim edir, lakin drawRect: draw(_:)-ə əl ilə yenilənmə tələb edir. Apple (2024) məlumatına görə, Swift versiyası draw(_:) yeni layihələr üçün üstünlük təşkil edir.

draw(_:)-də çəkmənin optimallaşdırılması

draw(_:) CPU-da icra olunur və optimallaşdırılmamış implementasiya kadr itkisinə və aşağı performansa səbəb ola bilər. Apple çəkməni sürətləndirmək üçün bir neçə sınaqdan keçmiş yanaşma tövsiyə edir.

Çəkmə əməliyyatlarının sayını minimuma endirin

Hər Core Graphics əməliyyatı (move(to:), addLine(to:), strokePath) əlavə yükə malikdir. Əməliyyatları qruplaşdırın və mürəkkəb fiqurlar üçün CGPath istifadə edin — yol bir dəfə yaradılır və hər draw(_:) çağırışında təkrar istifadə olunur.

Vektor obyektləri üçün UIBezierPath istifadə edin

UIBezierPath — CGPath üzərində Objective-C qabığıdır ki, fiqurlar yaratmaq üçün sadə API təqdim edir. UIBezierPath-i əvvəlcədən yaradın (məsələn, init-də) və draw(_:) daxilində sadəcə fill() və ya stroke() çağırın.

swift
private let starPath: UIBezierPath = {
    let path = UIBezierPath()
    // Ulduz forması yaratmaq
    path.move(to: CGPoint(x: 50, y: 0))
    for i in 1...5 {
        let angle = CGFloat(i) * 4 * CGFloat.pi / 5
        path.addLine(to: CGPoint(x: 50 + 40 * cos(angle),
                               y: 50 + 40 * sin(angle)))
    }
    path.close()
    return path
}()

override func draw(_ rect: CGRect) {
    UIColor.systemYellow.setFill()
    starPath.fill()
}

draw(_:) ilə işləyərkən tipik səhvlər

Proqramçılar draw(_:)-i yenidən təyin edərkən tez-tez eyni səhvlərə yol verirlər. Bu nümunələri bilmək səhvlərdən və performansın azalmasından qaçmağa kömək edir. Ən çox yayılmış problemlərə və onların həllərinə baxaq.

  • draw(_:)-in birbaşa çağırışı — heç vaxt draw(_:)-i birbaşa çağırmayın. Yenidən çəkmə tələb etmək üçün setNeedsDisplay() istifadə edin. Birbaşa çağırış keşləməni pozur və səhv göstərimə səbəb ola bilər.
  • draw(_:) daxilində ağır hesablamalar — draw(_:) mümkün qədər yüngül olmalıdır. UIBezierPath, şəkillər və digər ağır obyektləri metodun xaricində, bir dəfə yaradın.
  • draw(_:) daxilində obyekt yaratma — UIColor, UIFont və UIGraphicsImageRenderer konstruksiyaları draw(_:) daxilində əlavə yaddaş yükü yaradır. Obyekt yaratmanı sinif xüsusiyyətlərinə çıxarın.
  • rect parametrinin nəzərə alınmaması — rect yenidən çəkmə tələb edən sahəni göstərir. rect-dən kənarda çəkmə sistem tərəfindən rədd edilir, lakin resurs sərf edir. Çəkmədən əvvəl rect ilə kəsişməni yoxlayın.
  • super.draw(rect)-in olmaması — UIView implementasiyası boş olsa da, Apple gələcək UIKit dəyişiklikləri ilə uyğunluq üçün super.draw(rect) çağırmağı tövsiyə edir.

Bu qaydalara əməl etməklə, iOS altında istənilən layihədə xüsusi görünüşlərin sabit və sürətli çəkilməsini təmin edəcəksiniz. draw(_:)-i Instruments (Core Animation) vasitəsilə profilləşdirin ki, real icra müddətini və dar boğazları görəsiniz.

Tez-tez verilən suallar

draw(_:)-i birbaşa çağırmaq olarmı?

Xeyr, birbaşa draw(_:) çağırışı Apple sənədləri tərəfindən qadağandır. Sistem özü çəkmə dövrünü idarə edir. Yenidən çəkmə tələb etmək üçün setNeedsDisplay() istifadə edin ki, bu da görünüşü ən yaxın render dövründə yenilənmə tələb edən kimi qeyd edir.

drawRect: draw(_:)-dən nə ilə fərqlənir?

Funksional olaraq bu metodlar eynidir. drawRect: Objective-C-də, draw(_:) Swift-də istifadə olunur. Hər ikisi yenidən çəkmə sahəsinin CGRect-ni alır və UIGraphicsGetCurrentContext() vasitəsilə eyni Core Graphics kontekstindən istifadə edir.

Niyə draw(_:) boş UIView üçün çağırılmır?

Apple renderinqi optimallaşdırır: UIView-in yenidən təyin edilmiş draw(_:)-i yoxdursa, sistem onun üçün bitmap konteksti yaratmır. Bu yaddaşa qənaət edir. Yenidən təyin etmə varsa, lakin metod çağırılmırsa — görünüş çərçivəsinin sıfır olmadığını və görünüşün göründüyünü yoxlayın.

Sistem draw(_:)-i nə qədər tez-tez çağırır?

Yalnız lazım olduqda: ilk renderinq, setNeedsDisplay()-dən sonra, bounds dəyişdikdə contentMode = .redraw ilə. Statik vəziyyətdə draw(_:) təkrar çağırılmır ki, bu da CPU və batareya resurslarına qənaət edir.

Swift-də super.draw(rect) çağırmaq lazımdırmı?

Apple yenidən təyin edilmiş metodun əvvəlində super.draw(rect) çağırmağı tövsiyə edir. UIView-in cari implementasiyası boş olsa da, super çağırışı gələcək UIKit versiyaları ilə uyğunluğu təmin edir və yaxşı təcrübədir.

Xülasə

  • draw(_:) / drawRect — Swift və Objective-C-də UIView-in əsas çəkmə metodu, sistem tərəfindən avtomatik çağırılır
  • CGContext — UIGraphicsGetCurrentContext() vasitəsilə draw(_:) daxilində mövcud olan Core Graphics qrafik konteksti
  • setNeedsDisplay() — yenidən çəkmə tələb etməyin düzgün yolu; draw(_:)-in birbaşa çağırışı qadağandır
  • İdempotentlik — düzgün keşləmə üçün draw(_:) eyni giriş məlumatları ilə eyni nəticə verməlidir
  • UIBezierPath — hər çağırışda CPU yükünü minimuma endirmək üçün yolları draw(_:) xaricində yaradın
  • Parametr rect — yenidən çəkmə sahəsini ehtiva edir; optimallaşdırma üçün intersection istifadə edin — onun hüdudlarından kənarda çəkməyin
  • Profilləşdirmə — yavaş əməliyyatları aşkar etmək üçün draw(_:) performansını Instruments Core Animation vasitəsilə yoxlayın

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun