@ViewBuilder হল SwiftUI-তে একটি result builder অ্যানোটেশন যা View শ্রেণিবিন্যাসের ডিক্লারেটিভ নির্মাণের জন্য ডিজাইন করা হয়েছে। Apple Developer Documentation, 2024 অনুসারে, @ViewBuilder একাধিক এক্সপ্রেশন এবং শর্তসাপেক্ষ লজিক সহ কোডের একটি ব্লককে Swift কম্পাইলারের বোধগম্য একটি একক View টাইপে রূপান্তরিত করে। এই অ্যানোটেশন ছাড়া, if/else এবং body-তে একাধিক উপাদান সহ পরিচিত ডিক্লারেটিভ SwiftUI সিনট্যাক্স ব্যবহার করা অসম্ভব হত।
মূল পয়েন্ট
@ViewBuilder একটি অ্যানোটেশন যা result builder প্যাটার্ন (SE-0289) প্রয়োগ করে, যা SwiftUI-কে ডিক্লারেটিভ সিনট্যাক্স ব্যবহার করে একাধিক View-কে একটি কম্পোজিশনে একত্রিত করতে দেয়। এটি স্বয়ংক্রিয়ভাবে একাধিক এক্সপ্রেশন, শর্তসাপেক্ষ নির্মাণ এবং ঐচ্ছিক মানগুলিকে তাদের সংশ্লিষ্ট টাইপে মোড়ক করে: 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-তে, আপনি ডিক্লারেটিভভাবে বর্ণনা করেন কোন View-গুলি প্রদর্শিত হওয়া উচিত, এবং 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 দিয়ে অন্তর্নিহিতভাবে অ্যানোটেটেড — আপনি কোডে এই অ্যানোটেশন দেখতে পান না, কিন্তু কম্পাইলার এটি স্বয়ংক্রিয়ভাবে প্রয়োগ করে। তবে, কাস্টম প্রপার্টির জন্য যা একাধিক View ফেরত দেয়, বা ক্লোজার প্যারামিটারের জন্য, অ্যানোটেশনটি স্পষ্টভাবে উল্লেখ করতে হবে।
সীমাবদ্ধতা 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 ব্যবহার করুন। ত্রুটি পরিচালনার জন্য, পৃথক View ব্যবহার করুন যা Result বা ঐচ্ছিক মান গ্রহণ করে।
সীমাবদ্ধতা 3 — ডিবাগিং জটিলতা। @ViewBuilder-এ ত্রুটি ঘটলে, কম্পাইলার দীর্ঘ বার্তা তৈরি করে যেখানে মূল কারণ খুঁজে পাওয়া কঠিন। সাধারণ সমস্যা: if/else শাখায় টাইপ অমিল, 10টি উপাদানের সীমা অতিক্রম করা, বা buildBlock-এর প্রয়োজনীয় ওভারলোডের অনুপস্থিতি।
প্যাটার্ন 1: if/else-এর মাধ্যমে শর্তসাপেক্ষ প্রদর্শন। @ViewBuilder-এর সবচেয়ে সাধারণ ব্যবহার। এটি টারনারি অপারেটর বা ফ্যাক্টরি মেথড ব্যবহার না করেই স্টেটের উপর ভিত্তি করে বিভিন্ন View দেখানোর অনুমতি দেয়।
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। ক্লোজারের মাধ্যমে চাইল্ড View গ্রহণ করে এমন পুনর্ব্যবহারযোগ্য কন্টেইনার তৈরি করতে ব্যবহৃত হয়। এটি লাইব্রেরি এবং 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 প্রয়োগ করে। তবে, কাস্টম প্রপার্টি, মেথড এবং ক্লোজার প্যারামিটারের জন্য যা একাধিক View ফেরত দেয়, অ্যানোটেশন স্পষ্টভাবে উল্লেখ করতে হবে। এটি ছাড়া, কম্পাইলার একাধিক এক্সপ্রেশন পরিচালনা করতে সক্ষম হবে না।
ঐচ্ছিক এক্সপ্রেশনের জন্য, buildIf মেথড ব্যবহার করা হয়, যা একটি ঐচ্ছিক View গ্রহণ করে এবং মান থাকলে তা ফেরত দেয়। মান nil হলে, buildIf nil ফেরত দেয় এবং উপাদান প্রদর্শিত হয় না। এটি body-র ভিতরে if let ব্যবহার করার অনুমতি দেয়।
হ্যাঁ, Swift 5.9 থেকে @ViewBuilder buildExpression মেথডের মাধ্যমে switch সমর্থন করে। কম্পাইলার প্রতিটি case শাখাকে সংশ্লিষ্ট buildEither কলে রূপান্তরিত করে। switch সমর্থন নেস্টেড if/else নির্মাণের তুলনায় কোডকে আরও পঠনযোগ্য করে তোলে।
সারাংশ
আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব
IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।
আরও পড়ুন