0Pricing
Swift Academy · درس

الحالة والإجراء والمختزل

نمذج الميزات كمختزلات نقية تعمل على الحالة.

الحالة والإجراء والمختزل درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 4 دروس في المجموع.

ما هي The Composable Architecture؟

إن The Composable Architecture، أو TCA، مكتبة لبناء تطبيقات Swift بهيكل متسق وقابل للاختبار. تتمحور حول ثلاثة أجزاء: State الذي يصف بيانات ميزتكم، وAction الذي يصف كل حدث يمكن أن يقع، وReducer الذي يطوّر الحالة استجابةً للإجراءات.

يجعل هذا التدفق أحادي الاتجاه الميزات قابلة للتنبؤ وسهلة الاختبار.

import ComposableArchitecture

// State holds data, Action describes events,
// a Reducer turns (state, action) into the next state.

ماكرو @Reducer

تُعرَّف الميزة كنوع مرفق بماكرو @Reducer. ينشئ الماكرو الشيفرة الداعمة، ويتيح لكم التصريح بـ State وAction وbody الخاص بالـ reducer معًا في وحدة متماسكة واحدة.

وفقًا للعرف، يُسمّى النوع باسم الميزة، مثل CounterFeature.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    // State, Action, and body go here
}

تعريف الحالة

يكون State عادةً بنيةً تخزّن جميع البيانات التي تحتاج إليها الميزة. ويتيح وسمها بـ @ObservableState لـ SwiftUI مراقبة التغييرات بدقة وإعادة عرض الأجزاء المتأثرة فقط.

أبقوا الحالة مقتضبة، واحسبوا القيم المشتقة، بحيث يكون هناك مصدر واحد للحقيقة.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable {
        var count = 0
    }
}

تعريف الإجراءات

إن Action تعداد يسرد كل حدث يمكن للميزة معالجته: نقرات المستخدم، والاستجابات، ونبضات المؤقت، وغير ذلك. تسمّي كل حالة فيه شيئًا حدث، لا أمرًا لتغيير الحالة مباشرةً.

تجعل أسماء الإجراءات الواضحة سلوك الميزة موضحًا لذاته.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable { var count = 0 }

    enum Action {
        case incrementTapped
        case decrementTapped
    }
}

جسم Reducer

يعيش منطق الـ reducer في خاصية محسوبة باسم body تعيد some ReducerOf<Self>. وداخلها تستخدمون Reduce مع دالة إغلاق تستقبل state القابلة للتغيير وaction الوارد.

تفرّعون بحسب الإجراء وتغيّرون الحالة وفقًا لذلك.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable { var count = 0 }
    enum Action { case incrementTapped, decrementTapped }

    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .incrementTapped:
                state.count += 1
                return .none
            case .decrementTapped:
                state.count -= 1
                return .none
            }
        }
    }
}

إعادة التأثيرات

يجب أن يعيد كل فرع من فروع الـ reducer قيمة Effect. تعني إعادة .none عدم وجود عمل غير متزامن إضافي يجب تنفيذه بعد تغيير الحالة.

عندما تحتاجون إلى تأثيرات جانبية، مثل استدعاء شبكة، تعيدون تأثيرًا ينفّذ ذلك العمل. ستستكشفون التأثيرات في درس لاحق.

import ComposableArchitecture

// Every reducer branch returns an Effect.
// No side effect needed? Return .none.
// Need async work? Return an effect describing it.
Reduce { state, action in
    state.count += 1
    return .none
}

تتمركز تغييرات الحالة

تتمثل إحدى القواعد الأساسية في TCA في أن الـ reducer وحده يغيّر الحالة، ولا يفعل ذلك إلا استجابةً للإجراءات. لا تغيّر العروض الحالة مباشرةً؛ بل ترسل إجراءات.

إن وجود هذا المكان المركزي الوحيد للتغييرات هو ما يجعل تدفق البيانات سهل التتبع والاختبار.

import ComposableArchitecture

// Views send actions; the reducer mutates state.
// store.send(.incrementTapped)  ->  state.count += 1
// No direct state mutation outside the reducer.

نمذجة إدخال المستخدم في الحالة

تخزّن الميزات الشبيهة بالنماذج الحقول القابلة للتحرير في State، وتضيف إجراءات للتغييرات. ويتيح استخدام الربط مع الخصائص لعناصر تحكم SwiftUI تحديثها من خلال إجراءات آمنة من ناحية النوع.

تتتبّع الميزة هنا حقلًا نصيًا ومفتاح تبديل.

import ComposableArchitecture

@Reducer
struct FormFeature {
    @ObservableState
    struct State: Equatable {
        var name = ""
        var isSubscribed = false
    }
    enum Action: BindableAction {
        case binding(BindingAction<State>)
    }
    var body: some ReducerOf<Self> {
        BindingReducer()
    }
}

إجراءات ذات قيم مرتبطة

يمكن للإجراءات حمل بيانات باستخدام القيم المرتبطة. هكذا تنمذجون النتائج الواردة، مثل عنصر جرى تحميله أو خطأ، بحيث يتمكن الـ reducer من تخزينها في الحالة.

يحمل إجراء الاستجابة هنا الرقم الذي جرى جلبه.

import ComposableArchitecture

@Reducer
struct NumberFeature {
    @ObservableState
    struct State: Equatable { var value = 0 }
    enum Action {
        case reloadTapped
        case responseReceived(Int)
    }
    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .reloadTapped:
                return .none
            case let .responseReceived(value):
                state.value = value
                return .none
            }
        }
    }
}

لماذا تفيد Equatable مع الحالة

يتيح توافق State مع Equatable لـ TCA اكتشاف ما إذا كانت الحالة قد تغيّرت فعلًا، ما يوفّر تحديثات دقيقة للعروض واختبارات شاملة. إنه متطلب صغير ذو فوائد كبيرة.

تتوافق معظم أنواع الحالات مع Equatable تلقائيًا، لأن خصائصها المخزّنة متوافقة معه أصلًا.

import ComposableArchitecture

@ObservableState
struct State: Equatable {
    var count = 0
    var title = ""
}
// Equatable enables change detection and test assertions.

بنية الميزة المكتملة

تُقرأ الميزة المكتملة من الأعلى إلى الأسفل: الماكرو، والحالة القابلة للمراقبة، وتعداد الإجراءات، وجسم الـ reducer. يعيش كل ما يتعلق بالميزة داخل نوع واحد، وهذا ما يجعل ميزات TCA قابلة للتركيب وسهلة المراجعة.

يتكرر هذا الهيكل المتسق في كل ميزة داخل التطبيق.

import ComposableArchitecture

@Reducer
struct CounterFeature {
    @ObservableState
    struct State: Equatable { var count = 0 }
    enum Action { case incrementTapped, decrementTapped }
    var body: some ReducerOf<Self> {
        Reduce { state, action in
            switch action {
            case .incrementTapped: state.count += 1; return .none
            case .decrementTapped: state.count -= 1; return .none
            }
        }
    }
}

فحص سريع: الأجزاء الثلاثة

استذكروا أدوار State وAction وReducer في TCA.

خلاصة: State وAction وReducer

تعلمتم جوهر ميزة TCA:

  • يعرّف @Reducer نوع ميزة يحتوي كل شيء في مكان واحد.
  • تخزّن @ObservableState على بنية بيانات الميزة، وتتيح مراقبتها بدقة.
  • يسرد تعداد Action كل حدث، مع إمكانية احتوائه على قيم مرتبطة.
  • يستخدم body الخاص بالـ reducer Reduce لتغيير الحالة وإعادة Effect، مع استخدام .none عند عدم الحاجة إلى تأثير جانبي.
  • يغيّر الـ reducer وحده الحالة، مما يحافظ على قابلية التنبؤ بتدفق البيانات.

ستربطون هذه الميزة بعد ذلك بـ SwiftUI باستخدام Store.

import ComposableArchitecture

// Recap: @Reducer + State + Action + body(Reduce)
// One type, one source of truth, predictable updates.

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

هل درس «الحالة والإجراء والمختزل» مجاني؟

نعم — نص درس «الحالة والإجراء والمختزل» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.

ماذا ستتعلم في «الحالة والإجراء والمختزل»؟

نمذج الميزات كمختزلات نقية تعمل على الحالة. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟

لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «الحالة والإجراء والمختزل»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟

نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. الحالة والإجراء والمختزل
  2. المخزن وتكامل SwiftUI
  3. التأثيرات والتبعيات
  4. تركيب الميزات واختبارها
← العودة إلى Swift Academy