SwiftUI এর ডিএসএলকে কী সক্ষম করে?


89

দেখে মনে হচ্ছে অ্যাপলের নতুন SwiftUIকাঠামোটিতে একটি নতুন ধরণের সিনট্যাক্স ব্যবহার করা হয়েছে যা কার্যকরভাবে একটি টিউপল তৈরি করে, তবে আরও একটি বাক্য গঠন রয়েছে:

var body: some View {
    VStack(alignment: .leading) {
        Text("Hello, World") // No comma, no separator ?!
        Text("Hello World!")
    }
}

এই সিনট্যাক্সটি আসলে কী তা সামলানোর চেষ্টা করে আমি জানতে পেরেছিলাম যে VStackএখানে ব্যবহৃত আরম্ভকারীটি () -> Content দ্বিতীয় প্যারামিটার হিসাবে টাইপটি বন্ধ করে নেয় , যেখানে Contentজেনেরিক প্যারামটি Viewবন্ধ হওয়ার মাধ্যমে অনুমান করা হয়। কোন ধরণের Contentঅনুমান করা হয় তা জানতে , আমি কোডটির কার্যকারিতা বজায় রেখে কিছুটা পরিবর্তন করেছি:

var body: some View {
    let test = VStack(alignment: .leading) {
        Text("Hello, World")
        Text("Hello World!")
    }

    return test
}

এটির সাথে, testনিজেকে টাইপের হতে প্রকাশ করে VStack<TupleView<(Text, Text)>>, যার অর্থ Contentটাইপ TupleView<Text, Text>। খোঁজাখুঁজি করে TupleView, আমি দেখতে পেলাম যে এটি নিজের থেকে উত্পন্ন একটি মোড়কের ধরণ যা SwiftUIকেবল এটি র্যাপ করা উচিত টিপলটি পেরিয়েই আরম্ভ করা যেতে পারে।

প্রশ্ন

এখন আমি ভাবছি যে পৃথিবীতে Textএই উদাহরণের দুটি উদাহরণকে কী হিসাবে রূপান্তর করা হয় TupleView<(Text, Text)>। এটি কি হ্যাক হয়ে গেছে SwiftUIএবং তাই নিয়মিত সুইফট সিনট্যাক্স অবৈধ? TupleViewএকটি হচ্ছে SwiftUIটাইপ এই ধৃষ্টতা সমর্থন করে। নাকি এই বৈধ সুইফট সিনট্যাক্স? যদি হ্যাঁ হয় তবে এটির বাইরে কেউ কীভাবে ব্যবহার করতে পারে SwiftUI?


4
developer.apple.com/documentation/swiftui/vstack/3278367-init শো একটি "কাস্টম অ্যাট্রিবিউট" যে @ViewBuilder developer.apple.com/documentation/swiftui/viewbuilder
মার্টিন আর

উত্তর:


111

মার্টিন বলেছেন , যদি আপনি ডকুমেন্টেশন তাকান VStackএর init(alignment:spacing:content:), আপনি দেখতে পারেন যে content:পরামিতি অ্যাট্রিবিউট হয়েছে @ViewBuilder:

init(alignment: HorizontalAlignment = .center, spacing: Length? = nil,
     @ViewBuilder content: () -> Content)

এই বৈশিষ্ট্যটি ViewBuilderপ্রকারটিকে বোঝায় , যদি আপনি উত্পন্ন ইন্টারফেসটি দেখে থাকেন তবে মনে হচ্ছে:

@_functionBuilder public struct ViewBuilder {

    /// Builds an empty view from an block containing no statements, `{ }`.
    public static func buildBlock() -> EmptyView

    /// Passes a single view written as a child view (e..g, `{ Text("Hello") }`)
    /// through unmodified.
    public static func buildBlock(_ content: Content) -> Content 
      where Content : View
}

@_functionBuilderঅ্যাট্রিবিউট "বলা একটি বেসরকারী বৈশিষ্ট্যের একটি অংশ ফাংশন বিল্ডার ", যা হয়েছে এখানে সুইফট বিবর্তনে গল্পটা , এবং সুইফট এর যে সংস্করণটি Xcode 11 জাহাজ, এটা SwiftUI ব্যবহার করা যেতে সক্ষম হবেন জন্য বিশেষভাবে বাস্তবায়িত।

কোনও ধরণের চিহ্ন @_functionBuilderচিহ্নিতকরণ এটিকে বিভিন্ন ঘোষণাপত্র যেমন ফাংশন, গণিত বৈশিষ্ট্য এবং এই ক্ষেত্রে ফাংশন ধরণের পরামিতিগুলির হিসাবে কাস্টম অ্যাট্রিবিউট হিসাবে ব্যবহার করার অনুমতি দেয়। এ জাতীয় এনোটোটেড ঘোষণাগুলি কোডের ব্লকগুলিকে রূপান্তর করতে ফাংশন নির্মাতা ব্যবহার করে:

  • বর্ণিত ফাংশনগুলির জন্য, কোডটির যে ব্লকটি রূপান্তরিত হয় তা হ'ল বাস্তবায়ন।
  • টীকায়িত গণিত বৈশিষ্ট্যের জন্য, কোডটির যে ব্লকটি রূপান্তরিত হয় তা হ'ল গ্রাহক।
  • ফাংশন প্রকারের টীকাকৃত প্যারামিটারগুলির জন্য, কোডের ব্লকটি রূপান্তরিত হয় যে কোনও ক্লোজার এক্সপ্রেশন যা এটিতে পাস (যদি থাকে)।

কোনও ফাংশন নির্মাতা কোডকে যেভাবে রূপান্তর করে তার বিল্ডার পদ্ধতির প্রয়োগের মাধ্যমে এটি সংজ্ঞায়িত করা হয় যেমন buildBlockঅভিব্যক্তিগুলির একটি সেট নেয় এবং সেগুলি একক মানে সংহত করে।

উদাহরণস্বরূপ, এক থেকে একাধিক ভিউ একত্রিত করে 1 থেকে 10 অনুসারে মাপসই পরামিতিগুলির জন্য ViewBuilderপ্রয়োগসমূহ :buildBlockViewTupleView

@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension ViewBuilder {

    /// Passes a single view written as a child view (e..g, `{ Text("Hello") }`)
    /// through unmodified.
    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কেবলমাত্র buildBlock10 টি প্যারামিটার পর্যন্ত সংজ্ঞায়িত করা হয়েছে, তাই যদি আমরা 11 টির মতামত সংজ্ঞায়িত করার চেষ্টা করি:

  var body: some View {
    // error: Static member 'leading' cannot be used on instance of
    // type 'HorizontalAlignment'
    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")
        // ...
        // up to 10 views
      }
      Group {
        Text("Hello world")
        // ...
        // up to 10 more views
      }
      // ...
    }

ViewBuilder এছাড়াও অন্যান্য ফাংশন বিল্ডার পদ্ধতিগুলি প্রয়োগ করে:

extension ViewBuilder {
    /// Provides support for "if" statements in multi-statement closures, producing
    /// ConditionalContent for the "then" branch.
    public static func buildEither<TrueContent, FalseContent>(first: TrueContent)
      -> ConditionalContent<TrueContent, FalseContent>
           where TrueContent : View, FalseContent : View

    /// Provides support for "if-else" statements in multi-statement closures, 
    /// producing ConditionalContent for the "else" branch.
    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স্পষ্টতার জন্য)।


4
ViewBuilderকেবলমাত্র buildBlock10 টি প্যারামিটার পর্যন্ত সংজ্ঞায়িত করা হয়েছে - এর অর্থ কি var body: some View11 টিরও বেশি পূর্বরূপ থাকতে পারে না?
লিনাসেফার্থ

4
@ লিনাসগেফার্থ বাস্তবে আমি মনে করি না যে লোকেরা প্রায়শই এই বিধিনিষেধের মধ্যে চলে আসবে, কারণ তারা সম্ভবত ForEachপরিবর্তে দৃশ্যের মতো কিছু ব্যবহার করতে চাইবে । তবে আপনি Groupএই বিধিনিষেধটিকে কার্যকরী করতে দর্শনটি ব্যবহার করতে পারেন, এটি দেখানোর জন্য আমি আমার উত্তর সম্পাদনা করেছি।
হামিশ

4
@ মান্ডিসাডাব্লু - আপনি নিজের মতামতগুলিতে দলবদ্ধ করতে পারেন এবং সেগুলি পুনরায় ব্যবহার করতে পারেন। আমি এটি নিয়ে কোনও সমস্যা দেখছি না। আমি এখনই ডাব্লুডাব্লুডিসিতে আছি, এবং সুইফটইউআই ল্যাব-এ একজন ইঞ্জিনিয়ারের সাথে কথা বলেছি - তিনি বলেছিলেন যে এটি এখনই সুইফটের একটি সীমাবদ্ধতা, এবং তারা সংবেদনশীল-ইশ নম্বর হিসাবে 10 নিয়ে গেছে। একবার ভ্যারিয়্যাডিক জেনেরিকটি সুইফ্টের সাথে পরিচিত হওয়ার পরে আমরা যতগুলি চাই তার পক্ষে অনেকগুলি "সাবভিউ" রাখতে সক্ষম হব।
লসিয়োয়াটি

4
সম্ভবত আরও আকর্ষণীয়, বিল্ডইটার পদ্ধতিগুলির কী অর্থ? দেখে মনে হচ্ছে আপনার উভয়কেই বাস্তবায়ন করা দরকার, এবং উভয়ের উভয়ই একই রিটার্নের টাইপ রয়েছে, কেন তারা প্রত্যেকে কেবল প্রশ্নের ধরণটি ফেরত দেয় না?
গুসুতাফু

4
এএসটিপ্রিন্টার বাগ সম্পর্কে আমার মন্তব্য অনুসরণ করে, ফাংশন বিল্ডার পিআর একীভূত হওয়ার পরে এটি মাস্টারের উপর ঠিক করা হবে
হামিশ

13

ডিএসএলস সম্পর্কিত বিভাগে সুইটস ডাব্লুডাব্লুডিসি ভিডিওতে নতুন কীতে অ্যানালগাসের জিনিসটি বর্ণিত হয়েছে (31: 15 ডলার থেকে শুরু হয়)। বৈশিষ্ট্যটি সংকলক দ্বারা ব্যাখ্যা করা হয় এবং সম্পর্কিত কোডে অনুবাদ করা হয়:

এখানে চিত্র বর্ণনা লিখুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.