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 एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें