draw(_:) / drawRect UIView क्लास (Swift में) और Objective-C में इसके समकक्ष (drawRect:) की एक विधि है, जो Core Graphics का उपयोग करके व्यू की सामग्री को रेंडर करने के लिए जिम्मेदार है। सिस्टम इस विधि को स्वचालित रूप से कॉल करता है जब व्यू पहली बार स्क्रीन पर दिखाई देता है और setNeedsDisplay() कॉल करने के बाद। Apple Documentation (2025) के अनुसार, draw(_:) एकमात्र ऐसी विधि है जहाँ डेवलपर के पास कस्टम ड्राइंग के लिए वर्तमान स्क्रीन का ग्राफिक्स कॉन्टेक्स्ट उपलब्ध होता है। draw(_:) को ओवरराइड करना कॉम्पोनेंट की उपस्थिति पर पूर्ण नियंत्रण देता है — सरल ज्यामितीय आकृतियों से लेकर जटिल एनिमेटेड ग्राफिक्स तक।
मुख्य बिंदु
draw(_:) UIView की एक इंस्टेंस विधि है जिसे UIKit व्यू की सामग्री रेंडर करने के लिए कॉल करता है। इस विधि के अंदर, डेवलपर को CGContext ग्राफिक्स कॉन्टेक्स्ट तक पहुँच मिलती है और वह लाइनें, भरण, टेक्स्ट और इमेज बनाने के लिए Core Graphics API का उपयोग करता है। Objective-C में drawRect: समान कार्य करता है लेकिन भिन्न सिंटैक्स के साथ: एकमात्र पैरामीटर एक CGRect है जो पुनः ड्राइंग क्षेत्र निर्दिष्ट करता है।
Apple Engineering (2024) के अनुसार, draw(_:) CPU-आधारित Bitmap Graphics Context रेंडरिंग के माध्यम से काम करता है, जो अधिकतम लचीलापन प्रदान करता है लेकिन CALayer की तुलना में अधिक संसाधनों की आवश्यकता होती है। draw(_:) का उपयोग करने का निर्णय ग्राफिक्स की जटिलता और प्रदर्शन आवश्यकताओं के आधार पर लिया जाता है।
Swift में, विधि को override func draw(_ rect: CGRect) के रूप में घोषित किया जाता है, जहाँ rect वह आयत है जिसे पुनः बनाने की आवश्यकता है। Objective-C में हस्ताक्षर - (void)drawRect:(CGRect)rect है। setNeedsDisplay(_:) के माध्यम से आंशिक पुनः ड्राइंग के दौरान rect पैरामीटर व्यू के bounds से छोटा हो सकता है।
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
CGContextFillRect(context, rect);
}
सिस्टम स्वचालित रूप से draw(_:) को कड़ाई से परिभाषित परिदृश्यों में कॉल करता है। इन ट्रिगर्स को समझने से अनावश्यक पुनः ड्राइंग से बचने और व्यू प्रदर्शन को अनुकूलित करने में मदद मिलती है। नीचे विधि के स्वचालित कॉल के सभी मामले सूचीबद्ध हैं।
Apple दस्तावेज़ चेतावनी देता है: draw(_:) को सीधे कभी न कॉल करें। सिस्टम स्वयं तय करता है कि ड्राइंग कब करनी है, और सीधा कॉल आंतरिक कैशिंग तंत्र को बाधित करता है। पुनः ड्राइंग का अनुरोध करने के लिए, हमेशा setNeedsDisplay() या setNeedsDisplay(_:) का उपयोग करें।
Swift में draw(_:) को ओवरराइड करना ग्राफिक्स कॉन्टेक्स्ट प्राप्त करने और उसके बाद Core Graphics कॉल के साथ शुरू होता है। ड्राइंग के तार्किक ब्लॉकों के लिए अलग-अलग विधियाँ बनाने की अनुशंसा की जाती है — इससे कोड पठनीयता और परीक्षण क्षमता में सुधार होता है।
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
// Line parameters
context.setStrokeColor(UIColor.darkGray.cgColor)
context.setLineWidth(2.0)
// Drawing a triangle
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()
}
इस उदाहरण में, draw(_:) 2 पिक्सेल मोटी गहरे भूरे रंग की रूपरेखा के साथ एक त्रिभुज बनाता है। Apple द्वारा विधि की शुरुआत में super.draw(rect) कॉल करने की अनुशंसा की जाती है ताकि पैरेंट ड्राइंग तर्क संरक्षित रहे, हालाँकि UIView का डिफ़ॉल्ट draw(_:) कार्यान्वयन खाली है।
draw(_:) का प्रत्येक कॉल समान इनपुट डेटा के साथ समान परिणाम देना चाहिए। यह सिस्टम को परिणाम कैश करने की अनुमति देता है और यदि व्यू की सामग्री नहीं बदली है तो draw(_:) को दोबारा कॉल नहीं करता। उपयोग न करें draw(_:) के अंदर यादृच्छिक मान, सिस्टम समय या नेटवर्क अनुरोध।
drawRect: ऐतिहासिक रूप से विधि का पहला संस्करण है, जो iOS 2.0 में Objective-C के साथ प्रकट हुआ। Swift में, विधि का नाम बदलकर draw(_:) कर दिया गया जिसमें बाहरी पैरामीटर _ का उपयोग किया गया। कार्यात्मक रूप से, विधियाँ समान हैं: दोनों पुनः ड्राइंग क्षेत्र का CGRect प्राप्त करती हैं और ग्राफिक्स कॉन्टेक्स्ट तक पहुँचने के लिए UIGraphicsGetCurrentContext() का उपयोग करती हैं।
| विशेषता | draw(_:) (Swift) | drawRect: (Objective-C) |
|---|---|---|
| हस्ताक्षर | override func draw(_ rect: CGRect) | - (void)drawRect:(CGRect)rect |
| super कॉल | super.draw(rect) | [super drawRect:rect] |
| कॉन्टेक्स्ट | UIGraphicsGetCurrentContext() | UIGraphicsGetCurrentContext() |
| rect पैरामीटर | rect: CGRect | CGRect rect |
| प्रदर्शन | समान | समान |
Objective-C से Swift में प्रोजेक्ट माइग्रेट करते समय, विधि का नाम बदलना पहले कार्यों में से एक है। Xcode एक स्वचालित कनवर्टर प्रदान करता है, लेकिन drawRect: को मैन्युअल रूप से draw(_:) में अपडेट करने की आवश्यकता होती है। Apple (2024) के अनुसार, Swift संस्करण draw(_:) नए प्रोजेक्ट्स के लिए प्राथमिकता है।
draw(_:) CPU पर चलता है, और एक सबऑप्टिमल कार्यान्वयन फ्रेम ड्रॉप और खराब प्रदर्शन का कारण बन सकता है। Apple ड्राइंग को गति देने के लिए कई सिद्ध दृष्टिकोणों की अनुशंसा करता है।
प्रत्येक Core Graphics संचालन (move(to:), addLine(to:), strokePath) में ओवरहेड होता है। संचालन को समूहित करें और जटिल आकृतियों के लिए CGPath का उपयोग करें — पथ एक बार बनाया जाता है और प्रत्येक draw(_:) कॉल पर पुनः उपयोग किया जाता है।
UIBezierPath CGPath पर एक Objective-C रैपर है जो आकृतियाँ बनाने के लिए एक सरल API प्रदान करता है। UIBezierPath को पहले से बनाएँ (उदाहरण के लिए, इनिशियलाइज़र में) और draw(_:) के अंदर बस fill() या stroke() कॉल करें।
private let starPath: UIBezierPath = {
let path = UIBezierPath()
// Building a star shape
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(_:) को ओवरराइड करते समय समान गलतियाँ करते हैं। इन पैटर्न को जानने से बग और प्रदर्शन में गिरावट से बचने में मदद मिलती है। आइए सबसे सामान्य समस्याओं और उनके समाधानों पर नज़र डालें।
इन नियमों का पालन करके, आप किसी भी iOS प्रोजेक्ट में स्थिर और तेज़ कस्टम व्यू ड्राइंग सुनिश्चित करेंगे। वास्तविक निष्पादन समय और बाधाओं को देखने के लिए Instruments (Core Animation) के माध्यम से draw(_:) को प्रोफ़ाइल करें।
अक्सर पूछे जाने वाले प्रश्न
नहीं, draw(_:) का सीधा कॉल Apple दस्तावेज़ द्वारा निषिद्ध है। सिस्टम स्वयं ड्राइंग चक्र प्रबंधित करता है। पुनः ड्राइंग का अनुरोध करने के लिए setNeedsDisplay() का उपयोग करें, जो निकटतम रेंडरिंग चक्र में व्यू को अपडेट की आवश्यकता के रूप में सही ढंग से चिह्नित करता है।
कार्यात्मक रूप से ये विधियाँ समान हैं। drawRect: Objective-C में उपयोग किया जाता है, draw(_:) Swift में। दोनों पुनः ड्राइंग क्षेत्र का CGRect प्राप्त करते हैं और UIGraphicsGetCurrentContext() के माध्यम से समान Core Graphics कॉन्टेक्स्ट का उपयोग करते हैं।
Apple रेंडरिंग को अनुकूलित करता है: यदि UIView में कोई ओवरराइडेड draw(_:) नहीं है, तो सिस्टम इसके लिए bitmap कॉन्टेक्स्ट नहीं बनाता। इससे मेमोरी बचती है। यदि ओवरराइड मौजूद है लेकिन विधि कॉल नहीं होती — जाँच करें कि व्यू का फ्रेम गैर-शून्य है और व्यू दृश्यमान है।
केवल आवश्यकता होने पर: पहला रेंडर, setNeedsDisplay() के बाद, contentMode = .redraw के साथ bounds बदलने पर। स्थिर अवस्था में, draw(_:) दोबारा कॉल नहीं किया जाता, जिससे CPU और बैटरी संसाधनों की बचत होती है।
Apple ओवरराइडेड विधि की शुरुआत में super.draw(rect) कॉल करने की अनुशंसा करता है। हालाँकि वर्तमान UIView कार्यान्वयन खाली है, super कॉल भविष्य के UIKit संस्करणों के साथ संगतता सुनिश्चित करता है और एक अच्छी प्रथा है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें