@ViewBuilder SwiftUI में एक result builder एनोटेशन है जो View पदानुक्रम के घोषणात्मक निर्माण के लिए डिज़ाइन किया गया है। Apple Developer Documentation, 2024 के अनुसार, @ViewBuilder कई अभिव्यक्तियों और सशर्त तर्क वाले कोड ब्लॉक को Swift कंपाइलर के लिए समझने योग्य एकल View प्रकार में बदल देता है। इस एनोटेशन के बिना, if/else और body में कई तत्वों के साथ परिचित घोषणात्मक SwiftUI सिंटैक्स का उपयोग करना असंभव होगा।
मुख्य बिंदु
@ViewBuilder एक एनोटेशन है जो result builder पैटर्न (SE-0289) को लागू करता है, जो SwiftUI को घोषणात्मक सिंटैक्स का उपयोग करके कई Views को एक रचना में संयोजित करने की अनुमति देता है। यह स्वचालित रूप से कई अभिव्यक्तियों, सशर्त निर्माणों और वैकल्पिक मानों को उनके संबंधित प्रकारों में लपेटता है: TupleView, ConditionalContent, OptionalContent।
result builders के आगमन से पहले, डेवलपर्स को मैन्युअल रूप से तत्वों को VStack या HStack में लपेटना पड़ता था, और सशर्त तर्क के लिए टर्नरी ऑपरेटरों या फ़ैक्टरी विधियों का उपयोग करना पड़ता था। @ViewBuilder ने SwiftUI सिंटैक्स को संक्षिप्त और पठनीय बना दिया, जिससे कोड लिखना संभव हो गया जो if/else और लूप के साथ सामान्य Swift जैसा दिखता है।
Swift Evolution SE-0289 के अनुसार, result builders एक सामान्य तंत्र है जो SwiftUI से बंधा नहीं है। @ViewBuilder इस तंत्र का एक कार्यान्वयन है, साथ ही स्ट्रिंग निर्माण के लिए @StringBuilder और अन्य DSL के लिए लाइब्रेरी कार्यान्वयन भी हैं। SwiftUI में, @ViewBuilder का उपयोग न केवल body के लिए बल्कि कंटेनरों (VStack, HStack, ZStack, List) के क्लोज़र पैरामीटर के लिए भी किया जाता है।
अनिवार्य UIKit में, आप स्पष्ट रूप से एक UIView बनाते हैं, उसके गुणों को कॉन्फ़िगर करते हैं और addSubview के माध्यम से इसे पदानुक्रम में जोड़ते हैं। @ViewBuilder के साथ SwiftUI में, आप घोषणात्मक रूप से वर्णन करते हैं कि कौन से Views प्रदर्शित होने चाहिए, और SwiftUI स्थिति परिवर्तनों के आधार पर तत्वों के निर्माण, अद्यतन और हटाने का प्रबंधन करता है।
Result builder Swift का एक तंत्र है जो स्थिर विधियों buildBlock, buildOptional, buildEither और अन्य के माध्यम से अभिव्यक्तियों के अनुक्रम को एकल समग्र मान में बदल देता है। जब कंपाइलर @ViewBuilder एनोटेशन देखता है, तो वह संकलन के दौरान स्वचालित रूप से इन विधियों को कोड ब्लॉक पर लागू करता है।
@resultBuilder
struct ViewBuilder {
static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)>
static func buildIf<C>(_ c: C?) -> C?
static func buildEither<T, F>(first: T) -> ConditionalContent<T, F>
static func buildEither<T, F>(second: F) -> ConditionalContent<T, F>
}
buildBlock 1 से 10 अभिव्यक्तियों को स्वीकार करता है और TupleView लौटाता है। प्रत्येक गणनीयता (अभिव्यक्तियों की संख्या) का अपना buildBlock ओवरलोड होता है: buildBlock
buildEither (first/second) if/else निर्माणों को संभालता है। प्रत्येक शाखा को संबंधित विधि में पास किया जाता है, और परिणाम ConditionalContent में लपेटा जाता है — एक प्रकार जो विशिष्ट शाखा प्रकारों को छिपाता है और SwiftUI के लिए एकीकृत इंटरफ़ेस प्रदान करता है।
SwiftUI में, body प्रॉपर्टी पहले से ही @ViewBuilder के साथ अंतर्निहित रूप से एनोटेट है — आप कोड में यह एनोटेशन नहीं देखते हैं, लेकिन कंपाइलर इसे स्वचालित रूप से लागू करता है। हालांकि, कस्टम प्रॉपर्टी के लिए जो कई Views लौटाती हैं, या क्लोज़र पैरामीटर के लिए, एनोटेशन को स्पष्ट रूप से निर्दिष्ट किया जाना चाहिए।
सीमा 1 — एक ब्लॉक में 10 तत्व। यह @ViewBuilder की सबसे प्रसिद्ध सीमा है। यदि आपको एक ही स्तर पर 10 से अधिक तत्व प्रदर्शित करने की आवश्यकता है, तो कंपाइलर एक त्रुटि उत्पन्न करेगा। समाधानों में Group, ForEach, List या उप-घटकों में विभाजन शामिल है। Group दृश्य नेस्टिंग नहीं जोड़ता है, लेकिन प्रत्येक Group एक तत्व के रूप में गिना जाता है।
struct ManyElementsView: View {
var body: some View {
Group {
Text("1"); Text("2"); Text("3")
Text("4"); Text("5"); Text("6")
Text("7"); Text("8"); Text("9")
}
Group {
Text("10"); Text("11"); Text("12")
}
}
}
सीमा 2 — कुछ निर्माणों के लिए समर्थन की कमी। @ViewBuilder do/catch, guard, for-in (ForEach के बिना) और अन्य नियंत्रण प्रवाह निर्माणों का समर्थन नहीं करता है। लूप के लिए, पहचान योग्य डेटा के साथ ForEach का उपयोग करें। त्रुटि प्रबंधन के लिए, अलग Views का उपयोग करें जो Result या वैकल्पिक मान स्वीकार करते हैं।
सीमा 3 — डिबगिंग जटिलता। @ViewBuilder में त्रुटियाँ होने पर, कंपाइलर विस्तृत संदेश उत्पन्न करता है जिसमें मूल कारण ढूंढना मुश्किल होता है। सामान्य समस्याएँ: if/else शाखाओं में प्रकार बेमेल, 10 तत्वों की सीमा से अधिक, या buildBlock के आवश्यक ओवरलोड की अनुपस्थिति।
पैटर्न 1: if/else के माध्यम से सशर्त प्रदर्शन। @ViewBuilder का सबसे सामान्य उपयोग मामला। यह टर्नरी ऑपरेटरों या फ़ैक्टरी विधियों के उपयोग के बिना स्थिति के आधार पर विभिन्न Views दिखाने की अनुमति देता है।
struct StatusView: View {
var status: LoadStatus
@ViewBuilder
var body: some View {
switch status {
case .loading:
ProgressView("Loading...")
case .loaded(let data):
DataView(data: data)
case .error(let message):
ErrorView(message: message)
}
}
}
पैटर्न 2: फ़ंक्शन और इनिशियलाइज़र पैरामीटर में @ViewBuilder। इसका उपयोग पुन: प्रयोज्य कंटेनर बनाने के लिए किया जाता है जो क्लोज़र के माध्यम से चाइल्ड Views स्वीकार करते हैं। यह लाइब्रेरी और UI घटकों के लिए मानक पैटर्न है।
struct SectionCard<Content: View>: View {
let title: String
@ViewBuilder let content: Content
var body: some View {
VStack(alignment: .leading) {
Text(title).font(.headline)
content
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(12)
}
}
पैटर्न 3: ForEach के साथ रचना। @ViewBuilder ForEach के साथ सही ढंग से काम करता है, जिससे डेटा ऐरे से तत्वों की गतिशील पीढ़ी संभव होती है। ForEach का प्रत्येक तत्व @ViewBuilder संदर्भ में एक अभिव्यक्ति के रूप में गिना जाता है।
कस्टम ViewBuilder एक उपयोगकर्ता-परिभाषित फ़ंक्शन या प्रॉपर्टी है जो @ViewBuilder से एनोटेट है और some View लौटाता है। ऐसे फ़ंक्शन जटिल प्रदर्शन तर्क को एनकैप्सुलेट करने और एप्लिकेशन के विभिन्न भागों में इसका पुन: उपयोग करने की अनुमति देते हैं।
struct FormRow<Content: View>: View {
let label: String
@ViewBuilder let content: Content
var body: some View {
HStack {
Text(label)
.frame(width: 120, alignment: .trailing)
content
}
}
}
// उपयोग:
FormRow(label: "Name") {
TextField("Enter name", text: $name)
}
FormRow(label: "Gender") {
Picker("Select", selection: $gender) {
Text("पुरुष").tag(Gender.male)
Text("महिला").tag(Gender.female)
}
}
महत्वपूर्ण नियम: @ViewBuilder के साथ एक कस्टम फ़ंक्शन को some View लौटाना चाहिए, न कि कोई ठोस प्रकार या View प्रोटोकॉल। केवल अपारदर्शी प्रकार ही रचना लचीलेपन को संरक्षित करते हुए ठोस कार्यान्वयन को छिपाने की अनुमति देता है।
प्रदर्शन: कस्टम @ViewBuilder फ़ंक्शन सीधे body कोड की तुलना में कोई अतिरिक्त ओवरहेड नहीं जोड़ते हैं। कंपाइलर कॉल को इनलाइन करता है और परिणामी कोड को अनुकूलित करता है। body को @ViewBuilder फ़ंक्शनों में विभाजित करने से प्रदर्शन का त्याग किए बिना पठनीयता में सुधार होता है।
अक्सर पूछे जाने वाले प्रश्न
@ViewBuilder एक result builder एनोटेशन है जो कई अभिव्यक्तियों और शर्तों वाले कोड ब्लॉक को एकल View प्रकार में बदल देता है। यह SwiftUI की घोषणात्मक UI के अंदर परिचित Swift सिंटैक्स (if/else, switch, वैकल्पिक अभिव्यक्तियाँ) का उपयोग करने की अनुमति देता है।
सीमा buildBlock के कार्यान्वयन से उत्पन्न होती है — प्रत्येक गणनीयता 1 से 10 के लिए विधि का एक अलग ओवरलोड मौजूद है। Swift variadic generics का समर्थन नहीं करता है, इसलिए ओवरलोड की संख्या निश्चित है। इससे बचने के लिए, Group, ForEach या उप-घटकों का उपयोग करें।
नहीं, View प्रोटोकॉल अंतर्निहित रूप से body प्रॉपर्टी पर @ViewBuilder लागू करता है। हालांकि, कस्टम प्रॉपर्टी, विधियों और क्लोज़र पैरामीटर के लिए जो कई Views लौटाते हैं, एनोटेशन को स्पष्ट रूप से निर्दिष्ट किया जाना चाहिए। इसके बिना, कंपाइलर कई अभिव्यक्तियों को संभालने में सक्षम नहीं होगा।
वैकल्पिक अभिव्यक्तियों के लिए, buildIf विधि का उपयोग किया जाता है, जो एक वैकल्पिक View स्वीकार करता है और यदि मान मौजूद है तो उसे लौटाता है। यदि मान nil है, तो buildIf nil लौटाता है और तत्व प्रदर्शित नहीं होता है। यह body के अंदर if let का उपयोग करने की अनुमति देता है।
हाँ, Swift 5.9 से @ViewBuilder buildExpression विधि के माध्यम से switch का समर्थन करता है। कंपाइलर प्रत्येक case शाखा को संबंधित buildEither कॉल में बदल देता है। switch का समर्थन नेस्टेड if/else निर्माणों की तुलना में कोड को अधिक पठनीय बनाता है।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें