draw(_:) va drawRect — bu nima, chaqirish va qayta belgilash

Muallif: IT Sectr Nashr etilgan: 2026-07-20 O'qish vaqti: 7 daq

draw(_:) / drawRect — bu UIView sinifining (Swift-da) va uning Objective-C-dagi (drawRect:) analogi bo'lgan, Core Graphics yordamida ko'rinish tarkibini chizish uchun javob beradigan metoddir. Tizim bu metodni ko'rinish ekranda birinchi marta paydo bo'lganda va setNeedsDisplay() chaqirilgandan so'ng avtomatik chaqiradi. Apple Documentation (2025) ma'lumotlariga ko'ra, draw(_:) dasturchiga maxsus chizish uchun joriy ekranning grafik kontekstiga kirish imkoniyati mavjud bo'lgan yagona usuldir. draw(_:) ni qayta belgilash komponentning tashqi ko'rinishi ustidan to'liq nazorat beradi — oddiy geometrik shakllardan tortib murakkab animatsiyali grafikagacha.

Asosiy

  • draw(_:) — Core Graphics orqali maxsus chizish uchun UIView metodi, dasturchi tomonidan to'g'ridan-to'g'ri chaqirilmaydi
  • drawRect: — Objective-C-dagi draw(_:) ning ekvivalenti, sintaktik farqlanadi, funksional jihatdan bir xil
  • CGContext — barcha chizish operatsiyalari uchun draw(_:) ichida mavjud bo'lgan grafik kontekst
  • setNeedsDisplay() — dasturchi tomonidan draw(_:) ni qayta chaqirishni so'rashning yagona to'g'ri usuli
  • UIGraphicsGetCurrentContext() — draw(_:) ichida joriy kontekstni olish funksiyasi, chizishdan oldin majburiy qadam

draw(_:) / drawRect nima

draw(_:) — UIKit ko'rinish tarkibini render qilish uchun chaqiradigan UIView namunaviy metodi. Bu metod ichida dasturchi CGContext grafik kontekstiga kirish imkoniyatiga ega bo'ladi va chiziqlar, to'ldirishlar, matn va tasvirlarni chizish uchun Core Graphics API dan foydalanadi. Objective-C-dagi drawRect: bir xil funktsiyani bajaradi, lekin boshqa sintaksis bilan: yagona parametr — qayta chiziladigan maydonni belgilaydigan CGRect.

Apple Engineering (2024) ma'lumotlariga ko'ra, draw(_:) CPU renderlash Bitmap Graphics Context orqali ishlaydi, bu maksimal moslashuvchanlikni ta'minlaydi, lekin CALayer bilan solishtirganda ko'proq resurslarni talab qiladi. draw(_:) dan foydalanish to'g'risidagi qaror grafika murakkabligi va ishlash talablariga asoslanadi.

Swift va Objective-C-dagi metod imzosi

Swift-da metod override func draw(_ rect: CGRect) sifatida e'lon qilinadi, bu yerda rect qayta chizilishi kerak bo'lgan to'rtburchakdir. Objective-C-da imzo - (void)drawRect:(CGRect)rect. rect parametri setNeedsDisplay(_:) orqali qisman qayta chizish vaqtida ko'rinishning bounds dan kichikroq bo'lishi mumkin.

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

Tizim draw(_:) ni qachon chaqiradi

Tizim draw(_:) ni qat'iy belgilangan stsenariylarda avtomatik chaqiradi. Ushbu tetiklarni tushunish keraksiz qayta chizishlardan qochish va ko'rinish ishlashini optimallashtirishga yordam beradi. Quyida metodning avtomatik chaqirilishining barcha holatlari keltirilgan.

  • Birinchi renderlash — ko'rinish birinchi marta iyerarxiyaga qo'shilganda va ekranda ko'rinadigan bo'lganda
  • setNeedsDisplay() — bu metod chaqirilgandan so'ng tizim tomonidan eng yaqin chizish siklida
  • setNeedsDisplay(_:) — xuddi shunday, lekin qayta chizish uchun aniq to'rtburchak ko'rsatilgan holda
  • contentMode — bounds o'zgarganda, agar contentMode qayta chizishni talab qilsa (masalan, .redraw)
  • setNeedsLayout() — ba'zi hollarda subview-larni qayta joylashtirishdan so'ng qayta chizish talab qilinishi mumkin

Apple hujjatlari ogohlantiradi: hech qachon draw(_:) ni to'g'ridan-to'g'ri chaqirmang. Tizim o'zi chizishni qachon bajarishni hal qiladi va to'g'ridan-to'g'ri chaqirish ichki keshlash mexanizmini buzadi. Qayta chizishni so'rash uchun har doim setNeedsDisplay() yoki setNeedsDisplay(_:) dan foydalaning.

Swift-da draw(_:) ni qanday qayta belgilash mumkin

Swift-da draw(_:) ni qayta belgilash grafik kontekstni olish va keyingi Core Graphics chaqiruvlari bilan boshlanadi. Chizishning mantiqiy bloklari uchun alohida metodlar yaratish tavsiya etiladi — bu kod o'qiluvchanligi va test qilinishini yaxshilaydi.

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

    guard let context = UIGraphicsGetCurrentContext() else { return }

    // Chiziq parametrlari
    context.setStrokeColor(UIColor.darkGray.cgColor)
    context.setLineWidth(2.0)

    // Uchburchak chizish
    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()
}

Ushbu misolda draw(_:) 2 piksel qalinlikdagi to'q kulrang kontur bilan uchburchak chizadi. super.draw(rect) ni metod boshida chaqirish Apple tomonidan ota-ona chizish mantiqini saqlab qolish uchun tavsiya etiladi, garchi UIView-dagi draw(_:) ning standart implementatsiyasi bo'sh bo'lsa ham.

draw(_:) ning idempotentlik qoidasi

draw(_:) ning har bir chaqiruvi bir xil kirish ma'lumotlari bilan bir xil natija berishi kerak. Bu tizimga natijani keshlash va ko'rinish tarkibi o'zgarmagan bo'lsa, draw(_:) ni qayta chaqirmaslik imkonini beradi. draw(_:) ichida tasodifiy qiymatlar, tizim vaqti yoki tarmoq so'rovlaridan foydalanmang.

Objective-C-da drawRect: va draw(_:) bilan farqi

drawRect: — tarixan iOS 2.0 bilan Objective-C bilan birga paydo bo'lgan metodning birinchi variantidir. Swift-da metod tashqi parametr _ yordamida draw(_:) deb nomlandi. Funksional jihatdan metodlar bir xil: ikkalasi ham qayta chizish maydonining CGRect-ni oladi va grafik kontekstga kirish uchun UIGraphicsGetCurrentContext() dan foydalanadi.

Xususiyatdraw(_:) (Swift)drawRect: (Objective-C)
Imzooverride func draw(_ rect: CGRect)- (void)drawRect:(CGRect)rect
Super chaqiruvisuper.draw(rect)[super drawRect:rect]
KontekstUIGraphicsGetCurrentContext()UIGraphicsGetCurrentContext()
Parametr rectrect: CGRectCGRect rect
IshlashBir xilBir xil

Loyihani Objective-C dan Swift ga migratsiya qilishda metodni qayta nomlash birinchi vazifalardan biridir. Xcode avtomatik konvertorni taqdim etadi, ammo drawRect: draw(_:) ga qo'lda yangilanishni talab qiladi. Apple (2024) ma'lumotlariga ko'ra, Swift versiyasi draw(_:) yangi loyihalar uchun afzal hisoblanadi.

draw(_:) da chizishni optimallashtirish

draw(_:) CPU-da bajariladi va optimallashtirilmagan implementatsiya kadr tushishi va past ishlashga sabab bo'lishi mumkin. Apple chizishni tezlashtirish uchun bir nechta tasdiqlangan yondashuvlarni tavsiya qiladi.

Chizish operatsiyalari sonini minimallashtiring

Har bir Core Graphics operatsiyasi (move(to:), addLine(to:), strokePath) qo'shimcha yukga ega. Operatsiyalarni guruhlang va murakkab shakllar uchun CGPath dan foydalaning — yo'l bir marta yaratiladi va har bir draw(_:) chaqiruvida qayta ishlatiladi.

Vektor obyektlari uchun UIBezierPath dan foydalaning

UIBezierPath — bu CGPath ustidagi Objective-C qobig'i bo'lib, shakllar yaratish uchun oddiy API taqdim etadi. UIBezierPath ni oldindan yarating (masalan, initsializatorda) va draw(_:) ichida shunchaki fill() yoki stroke() ni chaqiring.

swift
private let starPath: UIBezierPath = {
    let path = UIBezierPath()
    // Yulduz shaklini yaratish
    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(_:) bilan ishlashda odatiy xatolar

Dasturchilar ko'pincha draw(_:) ni qayta belgilashda bir xil xatolarga yo'l qo'yadilar. Ushbu naqshlarni bilish xatolar va ishlashning pasayishidan qochishga yordam beradi. Eng keng tarqalgan muammolar va ularning yechimlarini ko'rib chiqaylik.

  • draw(_:) ni to'g'ridan-to'g'ri chaqirish — hech qachon draw(_:) ni to'g'ridan-to'g'ri chaqirmang. Qayta chizishni so'rash uchun setNeedsDisplay() dan foydalaning. To'g'ridan-to'g'ri chaqirish keshlashni buzadi va noto'g'ri ko'rsatishga olib kelishi mumkin.
  • draw(_:) ichida og'ir hisoblashlar — draw(_:) imkon qadar yengil bo'lishi kerak. UIBezierPath, tasvirlar va boshqa og'ir obyektlarni metod tashqarisida, bir marta yarating.
  • draw(_:) ichida obyekt yaratish — UIColor, UIFont va UIGraphicsImageRenderer konstruksiyalari draw(_:) ichida qo'shimcha xotira yukini yaratadi. Obyekt yaratishni sinf xususiyatlariga ko'chiring.
  • rect parametrini e'tiborsiz qoldirish — rect qayta chizishni talab qiladigan maydonni ko'rsatadi. rect dan tashqarida chizish tizim tomonidan rad etiladi, lekin resurslarni sarflaydi. Chizishdan oldin rect bilan kesishmani tekshiring.
  • super.draw(rect) ning yo'qligi — UIView implementatsiyasi bo'sh bo'lsa ham, Apple kelajakdagi UIKit o'zgarishlari bilan moslik uchun super.draw(rect) ni chaqirishni tavsiya qiladi.

Ushbu qoidalarga rioya qilgan holda, siz iOS-dagi har qanday loyihada maxsus ko'rinishlarning barqaror va tez chizilishini ta'minlaysiz. draw(_:) ni Instruments (Core Animation) orqali profiling qiling haqiqiy bajarilish vaqti va tor joylarni ko'rish uchun.

Tez-tez beriladigan savollar

draw(_:) ni to'g'ridan-to'g'ri chaqirish mumkinmi?

Yo'q, draw(_:) ni to'g'ridan-to'g'ri chaqirish Apple hujjatlari tomonidan taqiqlangan. Tizim o'zi chizish siklini boshqaradi. Qayta chizishni so'rash uchun setNeedsDisplay() dan foydalaning, u ko'rinishni eng yaqin renderlash siklida yangilanishi kerak deb to'g'ri belgilaydi.

drawRect: draw(_:) dan nima bilan farq qiladi?

Funksional jihatdan bu metodlar bir xil. drawRect: Objective-C da, draw(_:) Swift da ishlatiladi. Ikkalasi ham qayta chizish maydonining CGRect-ni oladi va UIGraphicsGetCurrentContext() orqali bir xil Core Graphics kontekstidan foydalanadi.

Nima uchun draw(_:) bo'sh UIView uchun chaqirilmaydi?

Apple renderlashni optimallashtiradi: agar UIView-da qayta belgilangan draw(_:) bo'lmasa, tizim uning uchun bitmap kontekst yaratmaydi. Bu xotirani tejaydi. Agar qayta belgilash mavjud bo'lsa, lekin metod chaqirilmasa — ko'rinish ramkasi nol emasligini va ko'rinish ko'rinadiganligini tekshiring.

Tizim draw(_:) ni qanchalik tez-tez chaqiradi?

Faqat kerak bo'lganda: birinchi renderlash, setNeedsDisplay() dan so'ng, bounds o'zgarganda contentMode = .redraw bilan. Statik holatda draw(_:) qayta chaqirilmaydi, bu CPU va batareya resurslarini tejaydi.

Swift-da super.draw(rect) chaqirish kerakmi?

Apple qayta belgilangan metod boshida super.draw(rect) ni chaqirishni tavsiya qiladi. UIView ning joriy implementatsiyasi bo'sh bo'lsa ham, super chaqiruvi kelajakdagi UIKit versiyalari bilan moslikni ta'minlaydi va yaxshi amaliyotdir.

Xulosa

  • draw(_:) / drawRect — Swift va Objective-C da UIView ning asosiy chizish metodi, tizim tomonidan avtomatik chaqiriladi
  • CGContext — UIGraphicsGetCurrentContext() orqali draw(_:) ichida mavjud bo'lgan Core Graphics grafik konteksti
  • setNeedsDisplay() — qayta chizishni so'rashning to'g'ri usuli; draw(_:) ni to'g'ridan-to'g'ri chaqirish taqiqlangan
  • Idempotentlik — to'g'ri keshlash uchun draw(_:) bir xil kirish ma'lumotlari bilan bir xil natija berishi kerak
  • UIBezierPath — har bir chaqiruvda CPU yukini minimallashtirish uchun yo'llarni draw(_:) tashqarisida yarating
  • Parametr rect — qayta chizish maydonini o'z ichiga oladi; optimallashtirish uchun intersection dan foydalaning — uning chegaralaridan tashqarida chizmang
  • Profiling — sekin operatsiyalarni aniqlash uchun draw(_:) ishlashini Instruments Core Animation orqali tekshiring

Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz

IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.

Loyihani muhokama qilish

Shuningdek o'qing