setNeedsDisplay(): metodning mohiyati va iOS-da qayta chizish mexanizmi

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

setNeedsDisplay() — bu UIView namuna metodi bo‘lib, ko‘rinishni qayta chizish talab qiladigan deb belgilaydi. To‘g‘ridan-to‘g‘ri draw(_:) chaqiruvidan farqli o‘laroq, setNeedsDisplay() faqat ko‘rinish uchun dirty bayrog‘ini o‘rnatadi va boshqaruvni darhol qaytaradi. Tizim bu so‘rovni eng yaqin render siklida qayta ishlaydi, bu bir nechta chaqiruvlarni bitta chizish operatsiyasida birlashtirishga imkon beradi. Apple Documentation (2025) ga ko‘ra, setNeedsDisplay() orqali kechiktirilgan qayta chizish moslashtirilgan UIView tarkibini yangilashning yagona to‘g‘ri usulidir.

Asosiy fikrlar

  • setNeedsDisplay() — UIView-ning kechiktirilgan qayta chizish so‘rovi, draw(_:) ni sinxron chaqirmaydi
  • dirty flag — setNeedsDisplay() tomonidan o‘rnatiladigan va draw(_:) dan keyin tiklanadigan ichki ko‘rinish bayrog‘i
  • setNeedsDisplay(_:) — faqat belgilangan hududning qisman qayta chizilishi uchun CGRect bilan yuklash
  • displayIfNeeded() — majburiy sinxron qayta chizish, zudlik bilan yangilash uchun ishlatiladi
  • Render sikli — tizim dirty ko‘rinishlarni run loop oxirida qayta ishlaydi, bir nechta so‘rovlarni bir o‘tishda birlashtiradi

setNeedsDisplay() nima

setNeedsDisplay() — bu UIView metodi bo‘lib, tizimga ko‘rinish tarkibi eskirganligi va qayta render talab qilishini bildiradi. Metod parametr qabul qilmaydi va void qaytaradi. Chaqiruvdan so‘ng ko‘rinish dirty deb belgilanadi va eng yaqin chizish siklida tizim ushbu ko‘rinish uchun draw(_:) ni chaqiradi.

Asosiy xususiyat asinxronlik dir. Bir ko‘rinish uchun ketma-ket bir nechta setNeedsDisplay() chaqiruvi bir nechta draw(_:) chaqiruviga olib kelmaydi — tizim ularni bitta operatsiyada birlashtiradi. Bu ishlash uchun juda muhim: agar ko‘rinish xususiyati kadrda bir necha marta o‘zgarsa, draw(_:) faqat bir marta chaqiriladi.

Kechiktirilgan qayta chizish qanday ishlaydi

Kechiktirilgan qayta chizish mexanizmi UIKit render sikliga asoslangan. setNeedsDisplay() chaqirilganda, tizim ichki layer.needsDisplay bayrog‘ini true ga o‘rnatadi. Joriy run loop oxirida tizim barcha dirty qatlamlardan o‘tib, har biri uchun draw(_:) ni chaqiradi.

Run loop va render bosqichlari

UIKit run loop dirty ko‘rinishlar qayta ishlanadigan update bosqichini o‘z ichiga oladi. Ushbu bosqichda kerak bo‘lsa layoutSubviews() chaqiriladi, so‘ng barcha belgilangan ko‘rinishlar uchun draw(_:) bajariladi. Chizish tugagandan so‘ng natija kompoziting uchun Core Animation orqali GPU ga uzatiladi.

swift
class ProgressView: UIView {
    var progress: CGFloat = 0 {
        didSet {
            setNeedsDisplay()
        }
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        guard let ctx = UIGraphicsGetCurrentContext() else { return }

        // Fon
        ctx.setFillColor(UIColor.lightGray.cgColor)
        ctx.fill(rect)

        // Progress bar
        let fillRect = CGRect(x: rect.minX, y: rect.minY,
                              width: rect.width * progress, height: rect.height)
        ctx.setFillColor(UIColor.systemGreen.cgColor)
        ctx.fill(fillRect)
    }
}

Ushbu misolda progressView progress ni yangilaydi va har bir setter avtomatik ravishda setNeedsDisplay() ni chaqiradi. Tizim run loop oxirini kutadi va draw(_:) ni joriy progress qiymati bilan chaqiradi. Agar progress bir kadrda uch marta o‘zgarsa, draw(_:) faqat bir marta — oxirgi qiymat bilan bajariladi.

setNeedsDisplay() vs setNeedsDisplay(_:)

setNeedsDisplay(_:) metodi qayta chizish hududini cheklovchi rect parametrini (CGRect turi) qabul qiladi. Bu ko‘rinishning faqat o‘zgargan qismini qayta chizishga imkon beradi, butunini emas. Ishlash farqi o‘zgarishlar kichik hududga ta‘sir qiladigan katta ko‘rinishlar bilan ishlaganda sezilarli bo‘ladi.

XususiyatsetNeedsDisplay()setNeedsDisplay(_:)
ParametrYo‘qCGRect — qayta chizish hududi
Qayta chizish hududiKo‘rinishning butun boundsFaqat belgilangan to‘rtburchak
IshlashKatta ko‘rinishlarda pastQisman o‘zgarishlarda yuqori
draw(_:) dagi rect parametriButun boundsBelgilangan to‘rtburchak
Qachon ishlatishButun tarkibning o‘zgarishiNuqtaviy o‘zgarishlar (kursor, highlight)

Murakkab grafikalar uchun avval butun sahnani offscreen kontekstida chizish, so‘ng faqat o‘zgargan hudud uchun setNeedsDisplay(_:) ni chaqirish tavsiya etiladi. Bu iOS-da chizish ilovalari va grafik muharrirlarida standart texnikadir.

displayIfNeeded() va setNeedsDisplay()

displayIfNeeded() — bu sinxron metod bo‘lib, run loop oxirini kutmasdan ierarxiyadagi barcha dirty ko‘rinishlarning qayta chizilishini darhol boshlaydi. Faqat bayroq o‘rnatadigan setNeedsDisplay() dan farqli o‘laroq, displayIfNeeded() draw(_:) ning darhol bajarilishini majburlaydi.

Apple displayIfNeeded() dan faqat o‘ta zarur hollarda foydalanishni tavsiya qiladi — masalan, skrinshot yaratishdan oldin yoki UIGraphicsImageRenderer uchun sinxron tasvir generatsiyasida. Oddiy stsenariylarda setNeedsDisplay() orqali asinxron model afzalroq, chunki u asosiy oqimni bloklamaydi.

swift
    // Asinxron — tavsiya etiladi
someView.setNeedsDisplay()

    // Sinxron — faqat kerak bo‘lganda
someView.setNeedsDisplay()
someView.displayIfNeeded() // draw(_:) darhol chaqirildi

Avval setNeedsDisplay() chaqirilmasdan displayIfNeeded() chaqiruvi samara bermaydi — metod faqat allaqachon dirty deb belgilangan ko‘rinishlarni qayta ishlaydi. Agar hech qanday ko‘rinish qayta chizishni talab qilmasa, displayIfNeeded() draw(_:) chaqirmasdan tugaydi.

setNeedsDisplay() chaqiruvlarini optimallashtirish

Tez-tez setNeedsDisplay() chaqiruvlari ishlashni pasaytirishi mumkin, ayniqsa animatsiya paytida. Asosiy optimallashtirish strategiyalarini ko‘rib chiqamiz.

Model orqali o‘zgarishlarni birlashtirish

Alohida xususiyatlarning har bir o‘zgarishida setNeedsDisplay() chaqirish o‘rniga, o‘zgarishlarni to‘plang va barcha yangilanishlar qo‘llanilgandan so‘ng metodni bir marta chaqiring. Masalan, elementning rangi, o‘lchami va joylashuvi o‘zgarganda — barcha xususiyatlar o‘rnatilgandan so‘ng bir marta setNeedsDisplay() chaqiring.

Animatsiya qilinadigan xususiyatlar uchun CALayer dan foydalanish

Agar xususiyat CALayer orqali animatsiya qilinishi mumkin bo‘lsa (backgroundColor, opacity, position, transform), draw(_:) o‘rniga Core Animation dan foydalaning. CALayer xususiyatlari draw(_:) chaqirmasdan GPU da yangilanadi, bu CPU ni yuklamasdan 60 FPS ni ta‘minlaydi.

CATransaction orqali to‘plam yangilash

Bir nechta o‘zgarishlarni bir render o‘tishida guruhlash uchun CATransaction dan foydalaning. Bu bir nechta setNeedsDisplay() ni tranzaksiya oxirida bitta draw(_:) operatsiyasida birlashtirishga imkon beradi.

swift
CATransaction.begin()
CATransaction.setDisableActions(true)

view1.setNeedsDisplay()
view2.setNeedsDisplay()
view3.setNeedsDisplay()

CATransaction.commit()

displayIfNeeded() dan suiiste‘mol qilmang — sinxron qayta chizish main thread ni bloklaydi va kadr tushishiga sabab bo‘lishi mumkin. Uni faqat joriy run loop tugashidan oldin chizish natijasi muhim bo‘lgan operatsiyalar uchun ishlating.

Ko‘p beriladigan savollar

setNeedsDisplay() o‘rniga to‘g‘ridan-to‘g‘ri draw(_:) chaqirish mumkinmi?

Yo‘q, to‘g‘ridan-to‘g‘ri draw(_:) chaqiruvi ta‘qiqlangan. setNeedsDisplay() ko‘rinishni to‘g‘ri dirty deb belgilaydi va tizim render siklining kerakli momentida draw(_:) ni chaqiradi. To‘g‘ridan-to‘g‘ri draw(_:) chaqiruvi keshlash mexanizmini e‘tiborsiz qoldiradi va nomuvofiq holatga olib kelishi mumkin.

Bir nechta setNeedsDisplay() chaqiruvlarida nima sodir bo‘ladi?

Bir ko‘rinish uchun bir nechta setNeedsDisplay() chaqiruvi tizim tomonidan bitta draw(_:) chaqiruvida birlashtiriladi. Bu metod faqat dirty flag ni o‘rnatgani uchun sodir bo‘ladi — bu bayroq faqat run loop oxirida draw(_:) haqiqiy bajarilishidan so‘ng tiklanadi.

setNeedsDisplay() setNeedsLayout() dan qanday farq qiladi?

setNeedsDisplay() ko‘rinish tarkibining qayta chizilishini so‘raydi (draw(_:) chaqiruvi). setNeedsLayout() subview-larning qayta joylashtirilishini so‘raydi (layoutSubviews() chaqiruvi). layoutSubviews() o‘lchamlarning o‘zgarishiga olib kelishi mumkin, bu esa o‘z navbatida qayta chizishni keltirib chiqarishi mumkin.

setNeedsDisplay(_:) qachon ishlatilishi kerak?

setNeedsDisplay(_:) nuqtaviy o‘zgarishlarda ishlatilishi kerak: kursor harakati, tanlangan hudud rangining o‘zgarishi, grafik qismining yangilanishi. Bu qayta chizish hududini cheklaydi va butun ko‘rinishning to‘liq qayta chizilishi bilan solishtirganda ishlashni oshiradi.

Frame o‘zgarishi avtomatik setNeedsDisplay() chaqiradimi?

Standart bo‘yicha frame yoki bounds o‘zgarishi setNeedsDisplay() chaqirmaydi. Tizim shunchaki ko‘rinishni harakatlantiradi. Agar o‘lcham o‘zgarishida qayta chizish talab qilinsa, contentMode xususiyatiga .redraw qiymatini o‘rnating — u holda UIKit bounds har o‘zgarganda avtomatik ravishda setNeedsDisplay() ni chaqiradi.

Xulosa

  • setNeedsDisplay() — dirty flag o‘rnatish orqali kechiktirilgan qayta chizish so‘rovi uchun UIView ning asinxron metodi
  • setNeedsDisplay(_:) — faqat belgilangan hududning qisman qayta chizilishi uchun CGRect bilan yuklash, ishlashni optimallashtiradi
  • displayIfNeeded() — dirty ko‘rinishlarni zudlik bilan qayta chizish uchun sinxron metod, faqat o‘ta zarur hollarda ishlatiladi
  • Run loop — tizim dirty ko‘rinishlarni joriy sikl oxirida qayta ishlaydi, bir nechta chaqiruvlarni bitta draw(_:) o‘tishida birlashtiradi
  • CALayer — animatsiya qilinadigan xususiyatlar (position, opacity) uchun draw(_:) o‘rniga Core Animation dan foydalaning — bu ancha samarali
  • CATransaction — bir nechta o‘zgarishlarni bir render siklida guruhlaydi, draw(_:) chaqiruvlari sonini kamaytiradi
  • contentMode = .redraw — ko‘rinish bounds o‘zgarganda avtomatik setNeedsDisplay() chaqiruvini yoqadi

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