0Pricing
Swift Academy · درس

بروتوكول Sendable

علّم الأنواع بأنها آمنة للعبور بين نطاقات التزامن.

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

ما الذي يعنيه Sendable؟

إن Sendable هو protocol مميز. ويضمن النوع المتوافق معه أنه آمن للمشاركة عبر نطاقات التزامن من دون التسبب في سباقات بيانات.

ولا يحتوي على أي دوال؛ بل يمثل ضمانًا تتحقق منه المترجم بشأن أمان الخيوط.

protocol Sendable {}

غالبًا ما تكون أنواع القيم Sendable

يمكن للبنى والتعدادات التي تكون جميع خصائصها المخزنة من النوع Sendable أن تتوافق معه تلقائيًا.

وبما أن القيم تُنسخ عند تمريرها، تحصل كل مهمة على نسخة مستقلة خاصة بها.

struct User: Sendable {
    let id: Int
    let name: String
}

التوافق الضمني

تحصل أنواع قيم كثيرة على Sendable ضمنيًا: البنى والتعدادات المجمّدة غير العامة التي تضم أعضاء Sendable، وtuples المكوّنة من أنواع Sendable، وmetatypes.

وغالبًا لا تحتاج إلى كتابة : Sendable مطلقًا لأنواع القيم الداخلية.

enum Direction { case north, south, east, west }
// Implicitly Sendable: no associated non-Sendable data

متى لا تكون البنية Sendable

إذا كان struct يحتوي على خاصية مخزنة غير Sendable، فلن يكون Sendable.

في هذه الحالة، يتيح مرجع الفئة الوصول إلى حالة قابلة للتغيير ومشتركة، لذلك يرفض المصرّف الامتثال التلقائي.

final class Box { var value = 0 }
struct Wrapper { // not Sendable
    let box: Box // class with mutable state
}

الفئات وSendable

الفئات أنواع مرجعية، ولذلك تشترك النسخ في المثيل نفسه. لا تكون الفئة Sendable إلا إذا كانت final وكانت جميع خصائصها المخزنة غير قابلة للتغيير ومتوافقة مع Sendable.

final class ImmutablePoint: Sendable {
    let x: Double
    let y: Double
    init(x: Double, y: Double) { self.x = x; self.y = y }
}

@unchecked Sendable

أحيانًا تعرف أن الفئة آمنة للاستخدام مع الخيوط (لأنها تحمي الحالة باستخدام قفل)، لكن المصرّف لا يستطيع إثبات ذلك. استخدم @unchecked Sendable لتؤكد السلامة يدويًا.

هذا منفذ للهروب: فأنت تتحمل مسؤولية صحة التنفيذ.

import Foundation
final class Cache: @unchecked Sendable {
    private let lock = NSLock()
    private var storage: [String: Int] = [:]
    func set(_ k: String, _ v: Int) {
        lock.lock(); defer { lock.unlock() }
        storage[k] = v
    }
}

عمليات الإغلاق @Sendable

يمكن أيضًا وسم عمليات الإغلاق بالرمز @Sendable. ويمكن تمرير عملية الإغلاق هذه عبر حدود التزامن، لذلك يتحقق المصرّف من أنها تلتقط قيمًا متوافقة مع Sendable فقط.

func run(_ work: @Sendable () -> Void) {
    work()
}
let name = "Ada" // immutable, Sendable
run { print(name) }

يُرفض التقاط الحالة القابلة للتغيير

لا يمكن لعملية إغلاق تحمل الوسم @Sendable أن تلتقط متغيرًا قابلًا للتغيير، لأن مهمتين قد تعدّلان قيمته في الوقت نفسه.

يضع المصرّف علامة على الالتقاط أدناه.

var counter = 0
// Error: @Sendable closure captures mutable var
// run { counter += 1 }

Sendable في واجهات API غير المتزامنة

تتطلب نقاط الدخول إلى التزامن Sendable. وعمليات إغلاق Task تحمل الوسم @Sendable، كما يجب أن تكون القيم الممررة إلى actors أخرى متوافقة مع Sendable.

بهذه الطريقة يمنع نظام الأنواع تسرب البيانات غير الآمنة مع الخيوط عبر المهام.

func process(_ user: User) async {
    Task {
        // user is Sendable, safe to capture
        print(user.name)
    }
}

قيود Sendable العامة

يمكنك اشتراط Sendable في الأنواع العامة. ويجب على الدالة التي تنشئ مهام باستخدام وسيطها أن تقيّد ذلك الوسيط ليكون من نوع Sendable.

func dispatch<T: Sendable>(_ value: T) {
    Task { print(value) }
}

Sendable في مقابل actor

يجيب Sendable عن السؤال: «هل تمرير هذه القيمة آمن؟»، بينما يجيب actor عن السؤال: «كيف أحمي الحالة القابلة للتغيير؟»

وهما يتكاملان: إذ تكون actors متوافقة ضمنيًا مع Sendable لأن الوصول إلى حالتها متسلسل.

actor Logger { } // actors are implicitly Sendable

تحقق سريع: Sendable

اختبر مدى فهمك لامتثال Sendable.

مراجعة: بروتوكول Sendable

يحدد Sendable الأنواع الآمنة للعبور عبر حدود التزامن. تمتثل أنواع القيم غير القابلة للتغيير تلقائيًا؛ ويمكن للفئات النهائية غير القابلة للتغيير أن تمتثل؛ أما الفئات الآمنة مع الخيوط فتستخدم @unchecked Sendable.

لا يمكن لعمليات الإغلاق @Sendable التقاط قيم إلا إذا كانت متوافقة مع Sendable، كما تتطلب واجهات API غير المتزامنة Sendable لمنع المشاركة غير الآمنة. وبالاقتران مع actors، يشكل Sendable الأساس على مستوى الأنواع لسلامة Swift من سباقات البيانات.

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

هل درس «بروتوكول Sendable» مجاني؟

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

ماذا ستتعلم في «بروتوكول Sendable»؟

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

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

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

كم من الوقت يستغرق درس «بروتوكول Sendable»؟

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

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

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

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

  1. مشكلة سباق البيانات
  2. بروتوكول Sendable
  3. عزل Actor و nonisolated
  4. الترحيل إلى التزامن الصارم
← العودة إلى Swift Academy