मार्टिन कहते हैं , अगर आप के लिए दस्तावेज़ को देखने VStack
के init(alignment:spacing:content:)
, आप देख सकते हैं कि content:
पैरामीटर विशेषता है @ViewBuilder
:
init(alignment: HorizontalAlignment = .center, spacing: Length? = nil,
@ViewBuilder content: () -> Content)
यह विशेषता उस ViewBuilder
प्रकार को संदर्भित करती है , जिसे यदि आप उत्पन्न इंटरफ़ेस को देखते हैं, तो यह दिखता है:
@_functionBuilder public struct ViewBuilder {
public static func buildBlock() -> EmptyView
public static func buildBlock(_ content: Content) -> Content
where Content : View
}
यह @_functionBuilder
विशेषता " फ़ंक्शन बिल्डरों " नामक एक अनौपचारिक विशेषता का एक हिस्सा है , जिसे यहां स्विफ्ट विकास पर पिच किया गया है , और स्विफ्ट के संस्करण के लिए विशेष रूप से कार्यान्वित किया गया है जो कि Xcode 11 के साथ जहाजों को स्विफ्टयूआई में उपयोग करने की अनुमति देता है।
एक प्रकार को चिह्नित करना @_functionBuilder
इसे विभिन्न घोषणाओं जैसे कि फ़ंक्शन, गणना किए गए गुणों और, इस मामले में, फ़ंक्शन प्रकार के मापदंडों पर एक कस्टम विशेषता के रूप में उपयोग करने की अनुमति देता है। ऐसी एनोटेट घोषणाएं कोड के ब्लॉक को बदलने के लिए फ़ंक्शन बिल्डर का उपयोग करती हैं:
- एनोटेट किए गए कार्यों के लिए, कोड का ब्लॉक जो रूपांतरित हो जाता है, वह है कार्यान्वयन।
- एनोटेट कंप्यूटेड संपत्तियों के लिए, कोड का ब्लॉक जो रूपांतरित हो जाता है, वह है।
- फ़ंक्शन प्रकार के एनोटेट किए गए मापदंडों के लिए, कोड का ब्लॉक जो रूपांतरित हो जाता है, वह कोई क्लोजर एक्सप्रेशन है जो इसे (यदि कोई हो) पास किया जाता है।
जिस तरह से एक फ़ंक्शन बिल्डर कोड को परिवर्तित करता है , उसे बिल्डर तरीकों के कार्यान्वयन द्वारा परिभाषित किया जाता है buildBlock
, जैसे कि अभिव्यक्ति का एक सेट लेता है और उन्हें एक एकल मूल्य में समेकित करता है।
उदाहरण के लिए, ViewBuilder
औजार buildBlock
1 से 10 के लिए View
अनुरूप मानकों, एक एकल में ऐसे कई दृश्य को मजबूत TupleView
:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension ViewBuilder {
public static func buildBlock<Content>(_ content: Content)
-> Content where Content : View
public static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1)
-> TupleView<(C0, C1)> where C0 : View, C1 : View
public static func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2)
-> TupleView<(C0, C1, C2)> where C0 : View, C1 : View, C2 : View
}
यह एक क्लोज़र VStack
में तब्दील होने के लिए पास किए गए व्यू एक्सप्रेशन के सेट buildBlock
को तर्कों की समान संख्या में ले जाने की अनुमति देता है। उदाहरण के लिए:
struct ContentView : View {
var body: some View {
VStack(alignment: .leading) {
Text("Hello, World")
Text("Hello World!")
}
}
}
एक कॉल में तब्दील हो जाता है buildBlock(_:_:)
:
struct ContentView : View {
var body: some View {
VStack(alignment: .leading) {
ViewBuilder.buildBlock(Text("Hello, World"), Text("Hello World!"))
}
}
}
जिसका परिणाम अपारदर्शी परिणाम प्रकार some View
से संतुष्ट किया जा रहा TupleView<(Text, Text)>
।
आप ध्यान देंगे कि ViewBuilder
केवल buildBlock
10 मापदंडों को परिभाषित करता है , इसलिए यदि हम 11 साक्षात्कारों को परिभाषित करने का प्रयास करते हैं:
var body: some View {
VStack(alignment: .leading) {
Text("Hello, World")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
Text("Hello World!")
}
}
हम एक कंपाइलर त्रुटि प्राप्त करते हैं, क्योंकि कोड के इस ब्लॉक को संभालने के लिए कोई बिल्डर विधि नहीं है (ध्यान दें कि क्योंकि यह सुविधा अभी भी एक कार्य-प्रगति है, इसके चारों ओर त्रुटि संदेश उतना उपयोगी नहीं होगा)।
वास्तव में, मुझे विश्वास नहीं है कि लोग इस प्रतिबंध में भाग लेंगे, जो अक्सर उदाहरण के लिए, उपरोक्त उदाहरण को ForEach
देखने के बजाय बेहतर उपयोग किया जाएगा:
var body: some View {
VStack(alignment: .leading) {
ForEach(0 ..< 20) { i in
Text("Hello world \(i)")
}
}
}
यदि आपको 10 से अधिक सांख्यिकीय रूप से परिभाषित विचारों की आवश्यकता है, तो आप आसानी से Group
दृश्य का उपयोग करके इस प्रतिबंध को हल कर सकते हैं :
var body: some View {
VStack(alignment: .leading) {
Group {
Text("Hello world")
}
Group {
Text("Hello world")
}
}
ViewBuilder
अन्य फ़ंक्शन बिल्डर विधियों को भी लागू करता है जैसे:
extension ViewBuilder {
public static func buildEither<TrueContent, FalseContent>(first: TrueContent)
-> ConditionalContent<TrueContent, FalseContent>
where TrueContent : View, FalseContent : View
public static func buildEither<TrueContent, FalseContent>(second: FalseContent)
-> ConditionalContent<TrueContent, FalseContent>
where TrueContent : View, FalseContent : View
}
यदि यह कथन को संभालने की क्षमता देता है:
var body: some View {
VStack(alignment: .leading) {
if .random() {
Text("Hello World!")
} else {
Text("Goodbye World!")
}
Text("Something else")
}
}
जो रूपांतरित हो जाता है:
var body: some View {
VStack(alignment: .leading) {
ViewBuilder.buildBlock(
.random() ? ViewBuilder.buildEither(first: Text("Hello World!"))
: ViewBuilder.buildEither(second: Text("Goodbye World!")),
Text("Something else")
)
}
}
(निरर्थक 1-तर्क का उत्सर्जन ViewBuilder.buildBlock
स्पष्टता के लिए कहता है )।
@ViewBuilder
है । developer.apple.com/documentation/swiftui/viewbuilder ।