أساسيات KeyPath
تعامل مع الخصائص كقيم من الدرجة الأولى.
أساسيات KeyPath درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 4 دروس في المجموع.
ما هو مسار المفتاح؟
مسار المفتاح هو قيمة تصف مساراً إلى خاصية من دون الوصول إليها فعلياً. فكّروا فيه كمرجع مخزّن وقابل لإعادة الاستخدام يحدّد أي خاصية تريدونها، بمعزل عن أي مثيل تقرؤونها منه.
تكتبون مسار المفتاح باستخدام شرطة مائلة عكسية، ثم اسم النوع، ثم نقطة، ثم اسم الخاصية. ويمنح Swift هذا التعبير قيمة من نوع KeyPath يمكنكم تمريرها مثل أي قيمة أخرى.
struct Person {
let name: String
let age: Int
}
let nameKeyPath = \Person.name
print(type(of: nameKeyPath))قراءة قيمة
لقراءة خاصية عبر مسار مفتاح، استخدموا الرمز الفرعي [keyPath:] على مثيل. مرّروا مسار المفتاح بين القوسين، وسيعيد Swift القيمة الموجودة في ذلك المسار.
يمثّل هذا النظير وقت التشغيل لكتابة اسم الخاصية مباشرة، لكن اختيار الخاصية يتم الآن بواسطة البيانات بدلاً من تثبيته في الشيفرة.
struct Person {
let name: String
let age: Int
}
let alice = Person(name: "Alice", age: 30)
let path = \Person.name
print(alice[keyPath: path])صياغة مسار المفتاح بالتفصيل
يتكوّن الشكل العام من رمز الشرطة المائلة العكسية، ثم النوع الجذر، ثم نقطة، ثم اسم الخاصية. ويشير رمز الشرطة المائلة العكسية إلى Swift بأنكم تريدون مسار مفتاح بدلاً من قيمة الخاصية.
النوع الجذر هو النوع الذي يبدأ منه المسار. أما نوع النتيجة فهو نوع الخاصية النهائية. لذلك فإن المسار من Person إلى خاصية age لديه جذر من نوع Person وقيمة من نوع Int.
struct Person {
let name: String
let age: Int
}
let ageKeyPath: KeyPath<Person, Int> = \Person.age
let bob = Person(name: "Bob", age: 42)
print(bob[keyPath: ageKeyPath])التسلسل عبر الخصائص المتداخلة
يمكن لمسارات المفاتيح التعمق داخل القيم المتداخلة. فإذا كانت إحدى الخصائص بنية بحد ذاتها، يمكنكم متابعة المسار بإضافة نقطة أخرى للوصول إلى خاصية أعمق.
تظل السلسلة بأكملها قيمة واحدة لمسار مفتاح، ويعكس نوعا الجذر والنتيجة بدايتها ونهايتها.
struct Address {
let city: String
}
struct Person {
let name: String
let address: Address
}
let cityPath = \Person.address.city
let carol = Person(name: "Carol", address: Address(city: "Oslo"))
print(carol[keyPath: cityPath])تخزين مسارات المفاتيح في المتغيرات
بما أن مسار المفتاح مجرد قيمة، يمكنكم تخزينه في متغير، أو إعادته من دالة، أو الاحتفاظ بمجموعة من مسارات المفاتيح. ويتيح لكم ذلك تحديد الخاصية التي ستقرؤونها أثناء التشغيل.
نختار هنا أحد مساري مفاتيح مخزّنين استناداً إلى علامة منطقية.
struct Person {
let name: String
let age: Int
}
let showAge = true
let chosen: PartialKeyPath<Person> = showAge ? \Person.age : \Person.name
let dave = Person(name: "Dave", age: 27)
print(dave[keyPath: chosen])PartialKeyPath وAnyKeyPath
يوفّر Swift مجموعة صغيرة من أنواع مسارات المفاتيح. يعرف KeyPath<Root, Value> كلا الطرفين. ويعرف PartialKeyPath<Root> الجذر، لكنه يتجاهل نوع القيمة. أما AnyKeyPath فيتجاهل كليهما.
كلما احتفظتم بمعلومات أكثر عن النوع، تمكن المترجم من إجراء مزيد من عمليات التحقق نيابة عنكم. ولا تلجؤوا إلى الشكلين الجزئي أو العام إلا عند الحاجة الفعلية إلى مزج مسارات ذات أنواع قيم مختلفة.
struct Person {
let name: String
let age: Int
}
let paths: [PartialKeyPath<Person>] = [\.name, \.age]
let eve = Person(name: "Eve", age: 19)
for p in paths {
print(eve[keyPath: p])
}الاختصار داخل نوع معروف
عندما يكون النوع الجذر معروفاً بالفعل من السياق، يمكنكم حذف اسم النوع وكتابة الشرطة المائلة العكسية والنقطة والخاصية فقط. وسيستنتج المترجم الجذر.
يجعل هذا الاختصار مواضع الاستدعاء أقصر، ولا سيما داخل عمليات المجموعات حيث يكون نوع العنصر واضحاً.
struct Person {
let name: String
let age: Int
}
func value(of person: Person, at path: KeyPath<Person, Int>) -> Int {
person[keyPath: path]
}
let frank = Person(name: "Frank", age: 55)
print(value(of: frank, at: \.age))مسارات المفاتيح كوسائط للدوال
من الأنماط الشائعة كتابة دالة عامة تقبل مسار مفتاح وتطبّقه على عدة مثيلات. ويفصل ذلك بين ما تقرؤونه والمنطق الذي ينفّذ القراءة.
تستخرج أداة المساعدة العامة هنا أي خاصية من أي نوع من قائمة الأشخاص.
struct Person {
let name: String
let age: Int
}
func extract<T>(_ people: [Person], _ path: KeyPath<Person, T>) -> [T] {
people.map { $0[keyPath: path] }
}
let people = [Person(name: "Ana", age: 21), Person(name: "Ben", age: 34)]
print(extract(people, \.name))
print(extract(people, \.age))مسارات المفاتيح والخصائص المحسوبة
تعمل مسارات المفاتيح للقراءة فقط مع الخصائص المحسوبة أيضاً. إذ يلتقط المسار عملية الحساب، ولذلك يؤدي المرور من خلاله إلى تشغيل getter.
وهذا يعني أن مسار المفتاح لا يقتصر على الخصائص المخزّنة؛ فأي خاصية قابلة للقراءة مؤهلة لذلك.
struct Rectangle {
let width: Double
let height: Double
var area: Double { width * height }
}
let areaPath = \Rectangle.area
let r = Rectangle(width: 3, height: 4)
print(r[keyPath: areaPath])مسار مفتاح الهوية
يوجد مسار مفتاح خاص يشير إلى القيمة بأكملها، ويُكتب بشرطة مائلة عكسية منفردة تليها نقطة ثم self. وتعيد القراءة من خلاله المثيل من دون تغيير.
ويفيد ذلك عندما تتطلب واجهة برمجة التطبيقات مسار مفتاح، بينما تريدون استخدام العنصر كما هو، مثل ترتيب الأرقام حسب قيمها نفسها.
let numbers = [3, 1, 2]
let identity = \Int.self
for n in numbers {
print(n[keyPath: identity])
}مقارنة مسارات المفاتيح
تتوافق مسارات المفاتيح مع Hashable وEquatable. ويكون مسارا مفتاح يشيران إلى الخاصية نفسها من النوع نفسه متساويين، لذا يمكنكم تخزينهما في مجموعات أو استخدامهما كمفاتيح في القواميس.
يفيد ذلك في إنشاء جداول تربط خاصية بتسمية أو أداة تنسيق.
struct Person {
let name: String
let age: Int
}
let labels: [PartialKeyPath<Person>: String] = [
\Person.name: "Full Name",
\Person.age: "Years Old"
]
print(labels[\Person.age] ?? "unknown")اختبار سريع: القراءة عبر مسار مفتاح
اختبروا مدى فهمكم لكيفية قراءة خاصية عبر مسار مفتاح.
مراجعة: أساسيات مسارات المفاتيح
تعلّمتم أساسيات مسارات المفاتيح:
- يُكتب مسار المفتاح باستخدام شرطة مائلة عكسية، ثم النوع الجذر، ثم نقطة، ثم اسم الخاصية، وهو يصف خاصية من دون قراءتها.
- اقرؤوا قيمة باستخدام الرمز الفرعي
[keyPath:]على مثيل. - يمكن للمسارات أن تتسلسل داخل الخصائص المتداخلة وأن تستهدف الخصائص المحسوبة.
- توازن الأنواع
KeyPathوPartialKeyPathوAnyKeyPathبين أمان النوع والمرونة. - مسارات المفاتيح قيم يمكن تخزينها وتمريرها ومقارنتها واستخدامها كمفاتيح في القواميس.
ستستخدمون بعد ذلك مسارات المفاتيح لجعل عمليات المجموعات أكثر إيجازاً بكثير.
struct Person {
let name: String
let age: Int
}
let path = \Person.age
let gina = Person(name: "Gina", age: 48)
print("Read via key path: \(gina[keyPath: path])")الأسئلة الشائعة
هل درس «أساسيات KeyPath» مجاني؟
نعم — نص درس «أساسيات KeyPath» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.
ماذا ستتعلم في «أساسيات KeyPath»؟
تعامل مع الخصائص كقيم من الدرجة الأولى. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟
لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «أساسيات KeyPath»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟
نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أساسيات KeyPath
- استخدام KeyPaths في المجموعات
- مسارات المفاتيح القابلة للكتابة والمرجعية
- @dynamicMemberLookup