Result Builder — ما هو، بناء الجملة والتطبيق

المؤلف: IT Sectr نُشر: 2026-06-20 وقت القراءة: 8 دق

Result Builder هي سمة Swift تُنفذ عبر البروتوكول @resultBuilder الذي يحول تسلسل التعبيرات إلى قيمة مركبة. يقوم المترجم بتحويل كتل التعليمات البرمجية مع تراكيب التحكم if، for، switch إلى استدعاءات لطرق ثابتة للباني — buildBlock، buildEither، buildArray. وفقاً لاقتراح Swift Evolution SE-0289 (2022)، تسمح result builders بإنشاء DSL تصريحي داخل Swift بدون محللات خارجية. المثال الأكثر شهرة هو @ViewBuilder في SwiftUI، حيث يتم بناء جسم العرض من عناصر شرطية ودورية بأسلوب تصريحي.

الخلاصة

  • Result Builder — سمة Swift تحول تسلسل التعبيرات إلى قيمة ناتجة عبر طرق ثابتة للباني
  • @ViewBuilder — المثال الأكثر شهرة: يحول عدة عناصر عرض إلى تمثيل مركب واحد TupleView
  • تراكيب التحكم — الباني يدعم if/else، switch، for-in عبر الطرق buildOptional، buildEither، buildArray
  • باني مخصص يمكن إنشاؤه لـ DSL الخاصة بك — HTML، CSS، التكوين، الاستعلامات
  • Swift 5.4 وسع دعم result builders للدوال ووسائط الدوال — الآن يمكن تطبيق باني على وسيطة إغلاق

ما هو Result Builder؟

Result Builder (المعروف سابقاً باسم function builders) هي آلية Swift تسمح بتحويل تسلسل من التعبيرات المفصولة بفواصل أسطر إلى قيمة واحدة. يتم الإعلان عنها باستخدام السمة @resultBuilder المطبقة على هيكل ينفذ طرق تحويل ثابتة.

قبل result builders، كانت البنية التصريحية لجسم SwiftUI مستحيلة. بدلاً من قائمة مضغوطة من عناصر العرض، كان على المطورين كتابة استدعاءات TupleView يدوياً. يقوم Result Builder تلقائياً بتغليف كل تعبير، ويدعم التفرع والحلقات، مخفياً تعقيد التركيب عن المطور.

وفقاً لـ Swift Evolution SE-0289، المقبول في 2022، فإن result builder هو تطور لفكرة function builders (SE-0258، Swift 5.1). التغييرات الرئيسية: إعادة التسمية من @_functionBuilder إلى @resultBuilder والتوسيع إلى وسائط الدوال، مما يسمح باستخدام البنائين لأي وسائط إغلاق، وليس فقط أجسام العرض.

استخدم result builders عندما تحتاج إلى تزويد مستخدمي مكتبتك ببنية تصريحية لبناء هياكل معقدة — تكوينات، استعلامات، مكونات واجهة مستخدم — دون كتابة كود تجميع أمري.

كيف يعمل Result Builder

يقوم مترجم Swift بتحويل كل كتلة تعليمات برمجية موسومة بـ @resultBuilder إلى تسلسل من استدعاءات الطرق الثابتة للباني. لنلق نظرة على باني بسيط يدمج السلاسل النصية:

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

استخدام هذا الباني — كل سلسلة في سطر منفصل تُدمج بمسافة:

swift
@StringBuilder
func greeting() -> String {
    "Hello"
    "World"
    "from"
    "Swift"
}
// يُحوّل المترجم هذا إلى:
// StringBuilder.buildBlock("Hello", "World", "from", "Swift")
// النتيجة: "Hello World from Swift"

يقوم المترجم بتجميع التعبيرات المتتالية ويمررها كوسائط متغيرة إلى buildBlock. إذا ظهر if بين التعبيرات، يستدعي المترجم buildOptional أو buildEither للتفرع. للحلقات for-in يستدعي buildArray. وهكذا، يتحول كود Swift العادي إلى سلسلة من الاستدعاءات التي تبني القيمة النهائية.

طرق الباني: buildBlock، buildOptional، buildEither

يحدد كل result builder مجموعة من الطرق الثابتة التي يستدعيها المترجم أثناء التحويل. الطرق الرئيسية:

الطريقةالغرضمتى تُستدعى
buildBlockيدمج تسلسل التعبيراتلكل كتلة بدون تفرع
buildOptionalيعالج if بدون elseعند وجود if بدون else
buildEither(first:)الفرع الأول من if-elseعند if مع else
buildEither(second:)الفرع الثاني من if-elseعند if مع else
buildArrayيعالج حلقات for-inعند وجود for-in
buildExpressionيحول التعبيرات الفرديةلكل تعبير قبل تمريره إلى buildBlock
buildFinalResultالتحويل النهائيقبل العودة من الإغلاق

يتطلب الحد الأدنى من التنفيذ فقط buildBlock مع وسائط متغيرة — وهذا كافٍ للكتل بدون تفرع. إضافة buildOptional و buildEither يتضمن دعم التراكيب الشرطية، و buildArray يتضمن الحلقات. وفقاً لوثائق Swift (2025)، يُوصى بتنفيذ جميع الطرق لتحقيق أقصى مرونة لـ DSL.

buildExpression يسمح بقبول تعبيرات من أنواع مختلفة وتحويلها إلى نوع واحد للباني. على سبيل المثال، في @ViewBuilder، buildExpression يقبل Text، Image، Button ويحولها إلى النوع المشترك View.

إنشاء Result 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()
    }
}

استخدام الباني المخصص لتوليد 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)، تُستخدم البنائين المخصصين في المكتبات لبناء ملفات التكوين، مكونات واجهة المستخدم، تعيين البيانات، وحتى استعلامات قاعدة البيانات — في أي مكان نحتاج فيه إلى بنية تصريحية مع دعم التفرع.

@ViewBuilder في SwiftUI

@ViewBuilder هو result builder مدمج في SwiftUI يُطبق على وسيطة content لمعظم عناصر العرض الحاوية: VStack، HStack، ZStack، Group، List، والخاصية body نفسها. يسمح بكتابة عدة عناصر عرض في أسطر منفصلة بدون فواصل أو أغلفة.

@ViewBuilder ينفذ جميع طرق result builder، بما في ذلك دعم if-else، switch، و for-in. عندما يتحقق الشرط، يُرجع buildEither(first:) عرضاً واحداً؛ عندما لا يتحقق، يُرجع buildEither(second:) عرضاً آخر. يجب أن يُرجع كلا الفرعين نفس النوع، لكن 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 القياسية تحميلات buildBlock لـ 2–10 تعابير. إذا كان في الكتلة أكثر من 10 تعابير، سيصدر المترجم خطأ. الحل هو التجميع عبر Group أو VStack لتقسيمها إلى كتل فرعية.

القيد الثاني هو عدم وجود دعم للمتغيرات والتعيينات داخل كتلة الباني. لا يمكنك تعريف let x = 5 داخل @ViewBuilder. يجب أن تكون كل التعبيرات تعابير تُرجع قيمة من نوع الباني. للحسابات الوسيطة، استخدم حسابات خارج الباني أو buildExpression مع دعم لأنواع مختلفة.

القيد الثالث هو تعقيد التصحيح. غالباً ما تنتج أخطاء الترجمة داخل result builder رسائل مربكة، خاصةً عندما لا تتطابق الأنواع في فروع if/else. استخدم أنواع إرجاع صريحة و AnyView للتصحيح، على الرغم من أن الأخير يقلل الأداء. وفقاً لـ Hacking with Swift (2025)، نصيحة عملية — ابدأ بباني بسيط بدون تفرع وأضف دعم التراكيب الشرطية تدريجياً.

الأسئلة الشائعة

ما هو Result Builder في Swift؟

Result Builder هي سمة Swift تحول تسلسل التعبيرات إلى قيمة ناتجة عبر طرق ثابتة. تسمح بإنشاء DSL تصريحي، المثال الأكثر شهرة هو @ViewBuilder في SwiftUI لبناء تسلسل هرمي للعرض بدون كود أمري.

كيف تنشئ Result Builder خاص بك؟

صرّح عن هيكل بالسمة @resultBuilder ونفذ على الأقل طريقة buildBlock. لدعم الشروط، أضف buildOptional و buildEither؛ للحلقات، أضف buildArray. استخدم سمة الباني قبل وسيطة الإغلاق في دالة.

ما الطرق الإلزامية لـ Result Builder؟

فقط buildBlock إلزامي. جميع الطرق الأخرى — buildOptional، buildEither، buildArray، buildExpression، buildFinalResult — اختيارية وتضيف دعم التراكيب المقابلة. كلما زاد عدد الطرق المنفذة، زادت مرونة DSL.

لماذا @ViewBuilder هو Result Builder؟

@ViewBuilder هو تطبيق ملموس لـ result builder لبروتوكول View. تم تعريفه في SwiftUI كهيكل بالسمة @resultBuilder، يوفر طرق buildBlock لعدد مختلف من عناصر العرض (TupleView)، buildEither لـ ConditionalContent و buildArray لـ ForEach.

هل هناك حد لعدد التعبيرات في الباني؟

نعم، تحميلات buildBlock القياسية تدعم حتى 10 تعابير. عند تجاوز ذلك، استخدم حاويات متداخلة (Group، VStack) للتقسيم إلى كتل فرعية. يمكن لباني مخصص تعريف buildBlock متغير بدون حد.

الملخص

  • Result Builder — سمة Swift تحول تسلسل التعبيرات إلى قيمة واحدة عبر طرق ثابتة للباني
  • المترجم يستبدل كتلة التعليمات البرمجية باستدعاءات buildBlock، buildEither، buildOptional، buildArray حسب تراكيب التحكم
  • @ViewBuilder — result builder المدمج في SwiftUI الذي يسمح بكتابة كود تصريحي للتسلسل الهرمي للعرض مع دعم الشروط والحلقات
  • بنائين مخصصين تُستخدم لبناء DSL: HTML، التكوينات، الاستعلامات — أي هيكل يستفيد من البنية التصريحية
  • القيود: حد أقصى 10 تعابير في buildBlock، لا يمكن تعريف المتغيرات، أخطاء ترجمة مربكة عند عدم تطابق الأنواع
  • Swift 5.4+ — يمكن تطبيق البنائين على وسائط الدوال، مما يوسع حالات الاستخدام خارج أجسام العرض

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا