Result Builder — چیست، نحوه نگارش و کاربرد

نویسنده: IT Sectr منتشر شده: 2026-06-20 زمان مطالعه: 8 دقیقه

Result Builder — یک ویژگی Swift است که از طریق پروتکل @resultBuilder پیاده‌سازی می‌شود و تسلسل عبارات را به یک مقدار ترکیبی تبدیل می‌کند. کامپایلر بلوک‌های کد با ساختارهای کنترلی if، for، switch را به فراخوانی‌های روش‌های ساکن بیلدر — buildBlock، buildEither، buildArray — تبدیل می‌کند. بر اساس Swift Evolution پیشنهاد SE-0289 (2022)، result builderها اجازه ایجاد DSLهای تصریحی در داخل Swift بدون تجزیه‌گرهای خارجی را می‌دهند. معروف‌ترین مثال — @ViewBuilder در SwiftUI، جایی که بدنه view از عناصر شرطی و حلقه‌ای به سبک تصریحی ساخته می‌شود.

نکات کلیدی

  • Result Builder — ویژگی Swift که تسلسل عبارات را از طریق روش‌های استاتیک بیلدر به مقدار نهایی تبدیل می‌کند
  • @ViewBuilder — معروف‌ترین مثال: چند view را به یک نمایش ترکیبی TupleView تبدیل می‌کند
  • ساختارهای کنترلی — بیلدر از if/else، switch، for-in از طریق روش‌های buildOptional، buildEither، buildArray پشتیبانی می‌کند
  • بیلدرهای سفارشی را می‌توان برای DSLهای خود ایجاد کرد — HTML، CSS، پیکربندی‌ها، پرس‌وجوها
  • Swift 5.4 پشتیبانی از result builderها را به توابع و پارامترهای تابع گسترش داد — اکنون می‌توان بیلدر را به آرگومان closure اعمال کرد

Result Builder چیست؟

Result Builder (قبلاً به عنوان function builders شناخته می‌شد) — مکانیزم Swift است که به شما اجازه می‌دهد تسلسل عبارات جداشده شده با خط جدید را به یک مقدار واحد تبدیل کنید. با استفاده از ویژگی @resultBuilder اعلام می‌شود که بر ساختاری اعمال می‌گردد که روش‌های استاتیک تبدیل را پیاده‌سازی می‌کند.

قبل از ظهور result builderها، نحوه نگارش تصریحی SwiftUI body ممکن نبود. به جای یک لیست مختصر از viewها، برنامه‌نویس مجبور بود به صورت دستی فراخوانی‌های TupleView را بنویسد. Result Builder به طور خودکار هر عبارت را می‌پیچد، شاخه و حلقه را پشتیبانی می‌کند و پیچیدگی ترکیب را از برنامه‌نویس پنهان می‌کند.

بر اساس Swift Evolution SE-0289 که در سال 2022 پذیرفته شد، result builder تکامل ایده function builders (SE-0258، Swift 5.1) است. تغییرات اصلی: تغییر نام از @_functionBuilder به @resultBuilder و گسترش به پارامترهای تابع، که اجازه استفاده از builderها را برای هر آرگومان closure داد، نه فقط برای بدنه view.

هر زمان که می‌خواهید به کاربران کتابخانه خود نحوه نگارش تصریحی برای ساخت ساختارهای پیچیده — پیکربندی‌ها، پرس‌وجوها، کامپوننت‌های UI — بدون نوشتن کد ساخت امری ارائه دهید، از result builderها استفاده کنید.

Result Builder چگونه کار می‌کند

کامپایلر Swift هر بلوک کد علامت‌گذاری شده با @resultBuilder را به یک تسلسل از فراخوانی روش‌های استاتیک بیلدر تبدیل می‌کند. ساده‌ترین builder را که رشته‌ها را به هم می‌پیوند، در نظر بگیرید:

swift
@resultBuilder
struct StringBuilder {
    static func buildBlock(_ parts: String...) -> String {
        parts.joined(separator: " ")
    }
}

استفاده از این builder — هر خط در یک رشته جداگانه با یک فاصله به هم می‌پیوند:

swift
@StringBuilder
func greeting() -> String {
    "Hello"
    "World"
    "from"
    "Swift"
}
// کامپایلر این را به این شکل تبدیل می‌کند:
// StringBuilder.buildBlock("Hello", "World", "from", "Swift")
// نتیجه: "Hello World from Swift"

کامپایلر عبارات متوالی را گروه‌بندی کرده و آنها را به عنوان پارامتر variadic به buildBlock ارسال می‌کند. اگر در بین عبارات if وجود داشته باشد، کامپایلر برای شاخه بندی buildOptional یا buildEither را فراخوان می‌کند. برای حلقه‌های for-in، buildArray فراخوان می‌شود. به این ترتیب، کد معمولی Swift به زنجیره‌ای از فراخوانی‌ها تبدیل می‌شود که مقدار نهایی را می‌سازند.

روش‌های بیلدر: buildBlock، buildOptional، buildEither

هر result builder یک مجموعه از روش‌های استاتیک را تعریف می‌کند که کامپایلر در طول تبدیل فراخوان می‌کند. روش‌های اصلی:

روشکاربردزمان فراخوانی
buildBlockتسلسل عبارات را ترکیب می‌کندبرای هر بلوک بدون شاخه
buildOptionalif بدون else را پردازش می‌کنددر وجود if بدون else
buildEither(first:)شاخه اول if-elseدر if با else
buildEither(second:)شاخه دوم if-elseدر if با else
buildArrayحلقه for-in را پردازش می‌کنددر وجود for-in
buildExpressionعبارت جداگانه را تبدیل می‌کندبرای هر عبارت قبل از ارسال به buildBlock
buildFinalResultتبدیل نهاییقبل از بازگشت از closure

پیاده‌سازی حداقل فقط buildBlock با پارامترهای variadic را نیاز دارد — این برای بلوک‌های بدون شاخه کافی است. افزودن buildOptional و buildEither پشتیبانی از ساختارهای شرطی را فعال می‌کند و buildArray — حلقه‌ها. بر اساس Swift Documentation (2025)، پیاده‌سازی تمام روش‌ها برای حداکثر انعطاف‌پذیری DSL توصیه می‌شود.

buildExpression به شما اجازه می‌دهد عبارات از انواع مختلف را بپذیرید و آنها را به نوع واحد builder تبدیل کنید. مثالاً، در @ViewBuilder، buildExpression عباراتی از نوع Text، Image، Button را پذیرفته و آنها را به نوع مشترک View تبدیل می‌کند.

ایجاد Result Builder سفارشی

ایجاد یک builder برای ساخت رشته‌های HTML را در نظر بگیرید. این DSL به شما اجازه می‌دهد HTML تصریحی را مستقیماً در Swift بنویسید:

swift
@resultBuilder
enum HTMLBuilder {
    static func buildBlock(_ components: String...) -> String {
        components.joined()
    }

    static func buildOptional(_ component: String?) -> String {
        component ?? ""
    }

    static func buildEither(first component: String) -> String {
        component
    }

    static func buildEither(second component: String) -> String {
        component
    }

    static func buildArray(_ components: [String]) -> String {
        components.joined()
    }
}

استفاده از builder سفارشی برای تولید HTML:

swift
func div(@HTMLBuilder _ content: () -> String) -> String {
    "<div>\(content())</div>"
}

func p(_ text: String) -> String {
    "<p>\(text)</p>"
}

let page = div {
    p("Hello")
    p("World")

    if showFooter {
        p("پاورقی")
    }
}
// نتیجه: <div><p>Hello</p><p>World</p><p>Footer</p></div>

بر اساس مقاله «Building Custom Result Builders in Swift» از Swift.org (2025)، builderهای سفارشی در کتابخانه‌ها برای ساخت فایل‌های پیکربندی، کامپوننت‌های UI، نقشه خوانی داده‌ها و حتی پرس‌وجوهای پایگاه داده استفاده می‌شوند — هر جایی که نحوه نگارش تصریحی با پشتیبانی از شاخه نیاز است.

@ViewBuilder در SwiftUI

@ViewBuilder — یک result builder ساخته شده در SwiftUI است که به پارامتر content اکثر کانتینرها اعمال می‌شود: VStack، HStack، ZStack، Group، List و خود ویژگی body. این امکان نوشتن چندین view در رشته‌های جداگانه بدون کاما و پیچونده ها را فراهم می‌کند.

@ViewBuilder تمام روش‌های result builder را از جمله پشتیبانی از if-else، switch و for-in پیاده می‌کند. وقتی شرط برقرار است، buildEither(first:) یک view را برمی‌گرداند؛ وقتی نیست — buildEither(second:) view دیگری را. هر دو شاخه باید همان نوع را بازگردانند، اما SwiftUI از AnyView داخلی یا از ConditionalContent برای پاک کردن نوع استفاده می‌کند.

swift
struct GreetingView: View {
    let isLoggedIn: Bool

    var body: some View {
        VStack {
            Image(systemName: "person.circle")
            Text("پروفایل")
                .font(.title)

            if isLoggedIn {
                Text("خوش آمدید!")
                    .foregroundColor(.green)
            } else {
                Button("ورود") { }
            }
        }
    }
}

بدون @ViewBuilder، همین کد برای هر بخش شرطی نیازمند Group یا استفاده از AnyView بود که عملکرد را کاهش می‌دهد. @ViewBuilder به طور خودکار کارآمدترین نمایش را — ConditionalContent یا TupleView — برای هر ترکیب انتخاب می‌کند.

محدودیت‌های Result Builder

محدودیت اول — حداکثر تعداد عبارات در buildBlock. کتابخانه استاندارد Swift برای 2–10 عبارت برای buildBlock سابرولود تعریف می‌کند. اگر در بلوک بیش از 10 عبارت وجود داشته باشد، کامپایلر خطا می‌دهد. راه حل — جداسازی به زیربلوک‌ها با استفاده از Group یا VStack.

محدودیت دوم — نبود پشتیبانی از متغیرها و تعیین مقادیر داخل بلوک builder. نمی‌توان let x = 5 را داخل @ViewBuilder اعلام کرد. همه عبارات باید عباراتی باشند که مقدار نوع builder را بازگردانند. برای محاسبات وسیط، از محاسبات خارج از builder یا buildExpression با پشتیبانی از انواع مختلف استفاده کنید.

محدودیت سوم — دشواری دباگ. خطاهای کامپایل داخل result builder اغلب پیام‌های گنجده می‌دهند، به ویژه در ناهماهنگی انواع در شاخه‌های if/else. برای دباگ از انواع صریح بازگشتی و AnyView استفاده کنید، هر چند آخری عملکرد را کاهش می‌دهد. به استناد به Hacking with Swift (2025)، توصیه عملی — با یک builder ساده بدون شاخه شروع کرده و پشتیبانی از ساختارهای شرطی را تدریجاً اضافه کنید.

سوالات متداول

Result Builder در Swift چیست؟

Result Builder — ویژگی Swift است که تسلسل عبارات را از طریق روش‌های استاتیک به مقدار نهایی تبدیل می‌کند. امکان ایجاد DSLهای تصریحی را فراهم می‌کند، معروف‌ترین مثال — @ViewBuilder در SwiftUI برای ساخت سلسله مراتب view بدون کد امری.

چگونه Result Builder خود را ایجاد کنم؟

یک ساختار با ویژگی @resultBuilder اعلام کرده و حداقل روش buildBlock را پیاده کنید. برای پشتیبانی از شرایط، buildOptional و buildEither را اضافه کرده، برای حلقه‌ها — buildArray. از ویژگی builder قبل پارامتر closure در تابع استفاده کنید.

کدام روش‌ها برای Result Builder اجباری هستند؟

فقط buildBlock اجباری است. سایر روش‌ها — buildOptional، buildEither، buildArray، buildExpression، buildFinalResult — اختیاری هستند و پشتیبانی از ساختارهای مربوطه را اضافه می‌کنند. هر چه روش‌های بیشتری پیاده شوند، DSL انعطاف‌پذیرتر خواهد بود.

چرا @ViewBuilder یک Result Builder است؟

@ViewBuilder — پیاده‌سازی مشخصی از result builder برای پروتکل View است. در SwiftUI به عنوان ساختاری با ویژگی @resultBuilder تعریف شده است که روش buildBlock را برای تعداد مختلف view (TupleView)، buildEither را برای ConditionalContent و buildArray را برای ForEach فراهم می‌کند.

آیا محدودیتی برای تعداد عبارات در builder وجود دارد؟

بله، سابرولودهای استاندارد buildBlock تا 10 عبارت را پشتیبانی می‌کنند. در صورت تجاوز، از کانتینرهای تودرتو (Group، VStack) برای تقسیم به زیربلوک‌ها استفاده کنید. یک builder سفارشی می‌تواند buildBlock بدون محدودیت با variadic تعریف کند.

خلاصه

  • Result Builder — ویژگی Swift که تسلسل عبارات را از طریق روش‌های استاتیک builder به یک مقدار واحد تبدیل می‌کند
  • کامپایلر بلوک کد را به فراخوانی‌های buildBlock، buildEither، buildOptional، buildArray بسته به ساختارهای کنترلی جایگزین می‌کند
  • @ViewBuilder — result builder ساخته شده در SwiftUI که نوشتن کد تصریحی سلسله مراتب view را با پشتیبانی از شرایط و حلقه‌ها امکان‌پذیر می‌کند
  • Builderهای سفارشی برای ساخت DSL استفاده می‌شوند: HTML، پیکربندی‌ها، پرس‌وجوها — هر ساختاری که از نحوه نگارش تصریحی بهره می‌برد
  • محدودیت‌ها: حداکثر 10 عبارت در buildBlock، نمی‌توان متغیر اعلام کرد، خطاهای گنجده کامپایل در ناهماهنگی انواع
  • Swift 5.4+ — builderها را می‌توان به پارامترهای تابع اعمال کرد که سناریوهای استفاده را فراتر از body view گسترش می‌دهد

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید