setNeedsDisplay() UIView کا ایک مثال طریقہ ہے جو ویو کو دوبارہ ڈرائنگ کی ضرورت کے طور پر نشان زد کرتا ہے۔ براہ راست draw(_:) کال کرنے کے برعکس، setNeedsDisplay() صرف ویو کے لیے dirty فلیگ سیٹ کرتا ہے اور فوری طور پر کنٹرول واپس کرتا ہے۔ سسٹم اس درخواست کو قریب ترین رینڈرنگ سائیکل میں پروسیس کرتا ہے، جس سے متعدد کالوں کو ایک ڈرا آپریشن میں یکجا کیا جا سکتا ہے۔ Apple دستاویزات (2025) کے مطابق، setNeedsDisplay() کے ذریعے التوا شدہ دوبارہ ڈرائنگ کسٹم UIView کے مواد کو اپ ڈیٹ کرنے کا واحد صحیح طریقہ ہے۔
اہم نکات
setNeedsDisplay() ایک UIView طریقہ ہے جو سسٹم کو اشارہ کرتا ہے کہ ویو کا مواد پرانا ہو گیا ہے اور دوبارہ رینڈر کرنے کی ضرورت ہے۔ یہ طریقہ کوئی پیرامیٹر نہیں لیتا اور void لوٹاتا ہے۔ کال کے بعد، ویو کو dirty کے طور پر نشان زد کیا جاتا ہے، اور قریب ترین ڈرا سائیکل میں سسٹم اس ویو کے لیے draw(_:) کال کرتا ہے۔
اہم خصوصیت غیر ہم وقتی ہے۔ ایک ہی ویو کے لیے لگاتار متعدد setNeedsDisplay() کالیں draw(_:) کی متعدد کالوں کا نتیجہ نہیں دیں گی — سسٹم انہیں ایک آپریشن میں یکجا کرتا ہے۔ یہ کارکردگی کے لیے انتہائی اہم ہے: اگر کوئی ویو پراپرٹی فی فریم کئی بار بدلتی ہے، تو draw(_:) صرف ایک بار کال ہوتا ہے۔
التوا شدہ دوبارہ ڈرائنگ کا میکانزم UIKit رینڈرنگ سائیکل پر مبنی ہے۔ جب setNeedsDisplay() کال کیا جاتا ہے، سسٹم اندرونی فلیگ layer.needsDisplay کو true پر سیٹ کرتا ہے۔ موجودہ run loop کے آخر میں، سسٹم تمام dirty لیئرز کا چکر لگاتا ہے اور ہر ایک کے لیے draw(_:) کال کرتا ہے۔
UIKit run loop میں ایک اپ ڈیٹ مرحلہ شامل ہے جس کے دوران dirty ویوز پروسیس ہوتی ہیں۔ اس مرحلے میں، اگر ضرورت ہو تو layoutSubviews() کال کیا جاتا ہے، پھر تمام نشان زدہ ویوز کے لیے draw(_:) کال کیا جاتا ہے۔ ڈرائنگ مکمل ہونے کے بعد، نتیجہ کمپوزٹنگ کے لیے Core Animation کے ذریعے GPU کو بھیجا جاتا ہے۔
class ProgressView: UIView {
var progress: CGFloat = 0 {
didSet {
setNeedsDisplay()
}
}
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let ctx = UIGraphicsGetCurrentContext() else { return }
// پس منظر
ctx.setFillColor(UIColor.lightGray.cgColor)
ctx.fill(rect)
// اقدام کا بار
let fillRect = CGRect(x: rect.minX, y: rect.minY,
width: rect.width * progress, height: rect.height)
ctx.setFillColor(UIColor.systemGreen.cgColor)
ctx.fill(fillRect)
}
}
اس مثال میں، progressView progress کو اپ ڈیٹ کرتا ہے، اور ہر سیٹر خود بخود setNeedsDisplay() کال کرتا ہے۔ سسٹم run loop کے ختم ہونے کا انتظار کرتا ہے اور حقیقی progress ویلیو کے ساتھ draw(_:) کال کرتا ہے۔ اگر progress فی فریم تین بار بدلتا ہے، تو draw(_:) صرف ایک بار عمل میں آتا ہے — آخری ویلیو کے ساتھ۔
setNeedsDisplay(_:) طریقہ CGRect قسم کا rect پیرامیٹر لیتا ہے، جو دوبارہ ڈرائنگ کے علاقے کو محدود کرتا ہے۔ یہ پورے ویو کے بجائے صرف تبدیل شدہ حصے کو دوبارہ ڈرا کرنے کی اجازت دیتا ہے۔ کارکردگی کا فرق بڑے ویوز کے ساتھ کام کرتے ہوئے نمایاں ہو جاتا ہے جہاں تبدیلیاں چھوٹے علاقے کو متاثر کرتی ہیں۔
| خصوصیت | setNeedsDisplay() | setNeedsDisplay(_:) |
|---|---|---|
| پیرامیٹر | کوئی نہیں | CGRect — دوبارہ ڈرائنگ کا علاقہ |
| دوبارہ ڈرائنگ کا علاقہ | پورے ویو کے bounds | صرف مخصوص مستطیل |
| کارکردگی | بڑے ویوز میں کم | جزوی تبدیلیوں میں زیادہ |
| draw(_:) میں rect پیرامیٹر | پورے bounds | مخصوص مستطیل |
| کب استعمال کریں | پورے مواد کی تبدیلی | نکاتی تبدیلیاں (کرسر، نمایاں) |
پیچیدہ گرافکس کے لیے، پہلے پورے منظر کو آف اسکرین سیاق و سباق میں ڈرا کرنے کی سفارش کی جاتی ہے، پھر صرف تبدیل شدہ علاقے کے لیے setNeedsDisplay(_:) کال کریں۔ یہ iOS پر ڈرائنگ ایپلیکیشنز اور گرافک ایڈیٹرز میں ایک معیاری تکنیک ہے۔
displayIfNeeded() ایک ہم وقت طریقہ ہے جو run loop کے ختم ہونے کا انتظار کیے بغیر درجہ بندی میں موجود تمام dirty ویوز کی دوبارہ ڈرائنگ فوری طور پر شروع کرتا ہے۔ setNeedsDisplay() کے برعکس، جو صرف ایک فلیگ سیٹ کرتا ہے، displayIfNeeded() draw(_:) کے فوری نفاذ کو مجبور کرتا ہے۔
Apple صرف انتہائی صورتوں میں displayIfNeeded() استعمال کرنے کی سفارش کرتا ہے جب ڈرائنگ کا نتیجہ فوری طور پر درکار ہو — مثال کے طور پر، اسکرین شاٹ لینے سے پہلے یا UIGraphicsImageRenderer کے لیے ہم وقت تصویر کی تخلیق کے دوران۔ عام منظرناموں میں، setNeedsDisplay() کے ذریعے غیر ہم وقتی ماڈل ترجیحی ہے کیونکہ یہ مرکزی تھریڈ کو مسدود نہیں کرتا۔
// غیر ہم وقت — تجویز شدہ
someView.setNeedsDisplay()
// ہم وقت — صرف ضرورت کی صورت میں
someView.setNeedsDisplay()
someView.displayIfNeeded() // draw(_:) فورا بلایا گیا
پہلے setNeedsDisplay() کے بغیر displayIfNeeded() کال کرنے کا کوئی اثر نہیں ہوگا — طریقہ صرف پہلے سے dirty نشان زدہ ویوز کو پروسیس کرتا ہے۔ اگر کسی ویو کو دوبارہ ڈرائنگ کی ضرورت نہیں ہے، تو displayIfNeeded() draw(_:) کال کیے بغیر مکمل ہو جاتا ہے۔
بار بار setNeedsDisplay() کالیں کارکردگی کو کم کر سکتی ہیں، خاص طور پر اینیمیشن کے دوران۔ آئیے اہم اصلاحی حکمت عملیوں پر نظر ڈالتے ہیں۔
ہر انفرادی پراپرٹی کی تبدیلی پر setNeedsDisplay() کال کرنے کے بجائے، تبدیلیوں کو جمع کریں اور تمام اپ ڈیٹس لاگو کرنے کے بعد ایک بار طریقہ کال کریں۔ مثال کے طور پر، کسی عنصر کا رنگ، سائز اور پوزیشن تبدیل کرتے وقت — تمام پراپرٹیز سیٹ کرنے کے بعد ایک بار setNeedsDisplay() کال کریں۔
اگر کوئی پراپرٹی CALayer (backgroundColor, opacity, position, transform) کے ذریعے اینیمیٹ کی جا سکتی ہے، تو draw(_:) کے بجائے Core Animation استعمال کریں۔ CALayer پراپرٹیز draw(_:) کال کیے بغیر GPU پر اپ ڈیٹ ہوتی ہیں، CPU بوجھ کے بغیر 60 FPS فراہم کرتی ہیں۔
متعدد تبدیلیوں کو ایک رینڈرنگ پاس میں گروپ کرنے کے لیے CATransaction استعمال کریں۔ یہ متعدد setNeedsDisplay() کالوں کو لین دین کے آخر میں ایک draw(_:) آپریشن میں یکجا کرنے کی اجازت دیتا ہے۔
CATransaction.begin()
CATransaction.setDisableActions(true)
view1.setNeedsDisplay()
view2.setNeedsDisplay()
view3.setNeedsDisplay()
CATransaction.commit()
displayIfNeeded() کا زیادہ استعمال نہ کریں — ہم وقت دوبارہ ڈرائنگ مرکزی تھریڈ کو مسدود کرتی ہے اور فریم ڈراپ کا سبب بن سکتی ہے۔ اسے صرف ان آپریشنز کے لیے استعمال کریں جہاں موجودہ run loop ختم ہونے سے پہلے ڈرائنگ کا نتیجہ اہم ہو۔
اکثر پوچھے گئے سوالات
نہیں، براہ راست draw(_:) کال کرنا ممنوع ہے۔ setNeedsDisplay() ویو کو dirty کے طور پر صحیح طریقے سے نشان زد کرتا ہے، اور سسٹم رینڈرنگ سائیکل کے مناسب وقت پر draw(_:) کال کرتا ہے۔ براہ راست draw(_:) کال کرنا کیشنگ میکانزم کو نظر انداز کرتا ہے اور غیر مطابقت پذیر حالت کا باعث بن سکتا ہے۔
ایک ہی ویو کے لیے setNeedsDisplay() کی متعدد کالیں سسٹم کے ذریعے ایک draw(_:) کال میں یکجا کر دی جاتی ہیں۔ یہ اس لیے ہوتا ہے کیونکہ طریقہ صرف dirty فلیگ سیٹ کرتا ہے، جو run loop کے آخر میں draw(_:) کے حقیقی نفاذ کے بعد ہی صاف ہوتا ہے۔
setNeedsDisplay() ویو کے مواد کی دوبارہ ڈرائنگ کی درخواست کرتا ہے (draw(_:) کال)۔ setNeedsLayout() ذیلی ویوز کی دوبارہ ترتیب کی درخواست کرتا ہے (layoutSubviews() کال)۔ layoutSubviews() سائز میں تبدیلی کا سبب بن سکتا ہے، جو بدلے میں دوبارہ ڈرائنگ کو متحرک کر سکتا ہے۔
setNeedsDisplay(_:) نکاتی تبدیلیوں کے لیے استعمال کیا جانا چاہیے: کرسر کی حرکت، منتخب علاقے کا رنگ تبدیل کرنا، گراف کے حصے کو اپ ڈیٹ کرنا۔ یہ دوبارہ ڈرائنگ کے علاقے کو محدود کرتا ہے اور پورے ویو کو دوبارہ ڈرا کرنے کے مقابلے میں کارکردگی کو بہتر بناتا ہے۔
پہلے سے طے شدہ طور پر، frame یا bounds تبدیل کرنا setNeedsDisplay() کال نہیں کرتا۔ سسٹم صرف ویو کو منتقل کرتا ہے۔ اگر سائز تبدیل کرنے پر دوبارہ ڈرائنگ کی ضرورت ہو تو، contentMode پراپرٹی کو .redraw پر سیٹ کریں — پھر UIKit خود بخود bounds کی ہر تبدیلی پر setNeedsDisplay() کال کرے گا۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں