Contacts في Swift: دليل شامل مع أمثلة تطبيقية
1. ما هي مكتبة Contacts ولماذا نستخدمها؟
مكتبة Contacts (إطار العمل Contacts.framework) هي واجهة برمجة التطبيقات (API) الرسمية من Apple للتعامل مع دفتر العناوين (جهات الاتصال) على أجهزة iOS و macOS و watchOS و tvOS. حلت هذه المكتبة محل الإطار القديم AddressBook وتوفر واجهة حديثة وموجهة للكائنات للوصول إلى جهات اتصال المستخدم. الهدف الأساسي للمكتبة هو توحيد عملية قراءة وإنشاء وتحديث وحذف جهات الاتصال، بالإضافة إلى إدارة المجموعات.
لماذا نحتاجها؟ أي تطبيق يتطلب التفاعل مع دفتر الهاتف (مثل تطبيقات المراسلة، أنظمة CRM، تطبيقات الاتصال، شبكات التواصل الاجتماعي) يجب أن يستخدم Contacts. تتيح المكتبة طلب أذونات المستخدم بأمان، وتحميل كميات كبيرة من البيانات بكفاءة (من خلال التحميل المتدرج واستخدام المسندات)، والتعامل مع جهات الاتصال الموحدة (عندما يتم دمج شخص واحد من عدة سجلات، مثل iCloud و Google).
على عكس الحلول القديمة، تدعم Contacts بشكل كامل لغة Swift (بما في ذلك async/await)، وتعمل مع CNContactStore كنقطة دخول موحدة، وتوفر كائنات غير قابلة للتغيير للقراءة وأخرى قابلة للتغيير للكتابة، مما يجعل الكود أكثر أمانًا وقابلية للتنبؤ.
2. التثبيت
مكتبة Contacts هي جزء من أطر عمل Apple النظامية. لست بحاجة إلى تثبيتها عبر مديري الحزم (CocoaPods, SPM أو Carthage) — فهي متوفرة بالفعل على الجهاز. لاستخدامها، يكفي استيراد الوحدة في الكود.
هام: للعمل مع جهات الاتصال، يجب إضافة المفتاح NSContactsUsageDescription إلى ملف Info.plist الخاص بمشروعك. بدون ذلك، سيتعطل التطبيق عند محاولة الوصول إلى المخزن.
الأمر (غير مطلوب، لكن للتوضيح):
نظرًا لأن هذا إطار نظام، لا توجد أوامر pip أو npm أو cargo. فقط أضف الاستيراد في ملف Swift:
import Contacts
3. بداية سريعة — مثال عملي بسيط
هذا المثال يطلب الإذن للوصول إلى جهات الاتصال ويطبع أسماء جميع جهات الاتصال من دفتر العناوين في وحدة التحكم.
import Contacts
import UIKit
// 1. إنشاء مثيل للمخزن
let store = CNContactStore()
// 2. طلب الإذن
store.requestAccess(for: .contacts) { granted, error in
guard granted else {
print("تم رفض الوصول: \(error?.localizedDescription ?? "خطأ غير معروف")")
return
}
// 3. إنشاء طلب جلب
let keysToFetch = [CNContactGivenNameKey, CNContactFamilyNameKey]
let request = CNContactFetchRequest(keysToFetch: keysToFetch)
// 4. تنفيذ الجلب
do {
try store.enumerateContacts(with: request) { contact, stopPointer in
print("تم العثور على جهة اتصال: \(contact.givenName) \(contact.familyName)")
}
} catch {
print("خطأ في جلب جهات الاتصال: \(error.localizedDescription)")
}
}
4. أهم الدوال/الفئات
4.1. CNContactStore
التوقيع: class CNContactStore : NSObject
الوظيفة: الفئة المركزية للوصول إلى قاعدة بيانات جهات الاتصال. من خلالها تتم جميع العمليات: الاستعلامات، الحفظ، الحذف.
مثال:
let store = CNContactStore()
// ثم نستخدم store لجميع العمليات
4.2. requestAccess(for:completionHandler:)
التوقيع: func requestAccess(for entityType: CNEntityType, completionHandler: @escaping (Bool, Error?) -> Void)
الوظيفة: