Share Extension هو امتداد iOS يُضيف تطبيقك إلى قائمة المشاركة النظامية. يمكن للمستخدم إرسال المحتوى من Safari أو الصور أو الملفات أو أي تطبيق آخر مباشرة إلى تطبيقك — دون نسخ أو التبديل بين النوافذ. وفقاً لأبل (2024)، التطبيقات التي تحتوي على Share Extension تحصل على 35% أكثر من محتوى المستخدم مقارنة بالتطبيقات بدون إمكانية المشاركة. يعالج الامتداد النصوص والصور والفيديو والروابط والملفات عبر واجهة NSExtensionItem الموحدة.
أهم النقاط
Share Extension هو نوع من امتدادات iOS يظهر في قائمة المشاركة النظامية عند تحديد المحتوى في أي تطبيق. يحدد المستخدم نصاً في Safari، ويضغط مشاركة، ويرى تطبيقك في قائمة الإجراءات المتاحة. بعد التحديد، يُمرر المحتوى إلى الامتداد لمعالجته: حفظه، نشره، إرساله أو تحويله.
على عكس Action Extension، يتخصص Share Extension في استقبال المحتوى من التطبيقات الخارجية. أما Action Extension فيرسل البيانات من تطبيقك إلى الخارج. Share Extension هو نقطة دخول لمحتوى المستخدم، عنصر أساسي في اكتساب المستخدمين: يجرب المستخدمون تطبيقك عبر Share Extension دون تثبيته بالكامل. يمنع App Store التطبيقات التي وظيفتها الوحيدة عرض الإعلانات عبر Share Extension (App Store Review Guideline 4.2).
يقلل Share Extension حاجز الدخول: يرسل المستخدمون المحتوى إلى تطبيقك من سياق مألوف — المتصفح، المعرض، مدير الملفات. وفقاً لـ Branch (2024)، التطبيقات التي تحتوي على Share Extension تُظهر احتفاظاً أعلى بنسبة 28% في اليوم السابع. تأثير إضافي هو الانتشار: في كل مرة يرى فيها المستخدم تطبيقك في ورقة المشاركة، يحدث علامة تجارية سلبية دون إنفاق على الإعلانات.
تعتمد آلية Share Extension على نقل المحتوى عبر حاويات NSExtensionItem النظامية. يقوم التطبيق المضيف (Safari، الصور) بتغليف المحتوى المحدد في NSExtensionItem مع نوع محدد (public.image، public.url، public.plain-text). يمرر النظام هذه الحاوية إلى الامتداد، الذي يستخرج البيانات عبر extensionContext.inputItems.
يعمل Share Extension في عملية منفصلة بوقت تنفيذ محدود — حوالي 30 ثانية للمعالجة. لا يجب على الامتداد تنفيذ عمليات طويلة متزامنة. لرفع الملفات الكبيرة، استخدم NSURLSession مع تهيئة خلفية. SLComposeServiceViewController هو الفئة الأساسية لـ Share Extension مع معاينة المحتوى وزر إرسال.
يستخدم iOS معرفات النوع الموحدة (UTI) لتحديد نوع المحتوى المنقول. UTI الرئيسية لـ Share Extension: public.image (الصور، لقطات الشاشة)، public.url (الروابط)، public.plain-text (النص)، public.video (ملفات الفيديو)، و public.file-url (الملفات). يسجل الامتداد UTI المدعومة في Info.plist عبر مفتاح NSExtensionActivationRule.
يتكون Share Extension من ثلاثة مكونات: الهدف في Xcode، وSLComposeServiceViewController، وتهيئة Info.plist. الهندسة تحدد أنواع المحتوى التي تتم معالجتها، وكيفية عرض الواجهة، وأين يتم حفظ البيانات.
| المكون | الغرض | الميزات |
|---|---|---|
| Target | هدف الامتداد في Xcode | حزمة منفصلة بمعرّف |
| ViewController | الواجهة ومنطق المعالجة | SLComposeServiceViewController أو مخصص |
| Info.plist | تهيئة التفعيل و UTI | NSExtensionActivationRule مع مسندات |
| App Groups | تخزين مشترك مع التطبيق | مجموعة UserDefaults لنقل البيانات |
العنصر الأساسي في تهيئة Share Extension هو قاعدة التفعيل. تحدد في أي الظروف يظهر الامتداد في ورقة المشاركة. تُحدد القاعدة في Info.plist كقاموس مع قيود: الحد الأقصى لعدد الصور، الحد الأدنى لطول النص، وجود URL إلزامي. القاعدة القياسية تفعّل الامتداد لأي نوع محتوى واحد.
// Info.plist — قاعدة تفعيل NSExtensionActivationRule لـ Share Extension
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>5</integer>
<key>NSExtensionActivationSupportsText</key>
<true/>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
</dict>
لننظر إلى مثال عملي لإنشاء Share Extension بلغة Swift لتطبيق إشارات مرجعية. يستقبل الامتداد URL من Safari، ويعرض واجهة معاينة، ويحفظ الرابط في App Group. SLComposeServiceViewController يوفر واجهة مستخدم جاهزة مع حقل نص وزر نشر.
import Social
import MobileCoreServices
class ShareViewController: SLComposeServiceViewController {
override func isContentValid() -> Bool {
return !(contentText?.isEmpty() ?? true)
}
override func didSelectPost() {
guard let item = extensionContext?.inputItems.first as? NSExtensionItem
else { return }
for attachment in item.attachments ?? [] {
attachment.loadItem(forTypeIdentifier: kUTTypeURL as String) {
[weak self] (item, error) in
if let url = item as? URL {
BookmarkService().save(url, title: self?.contentText)
}
self?.extensionContext?.completeRequest(
returningItems: [], completionHandler: nil)
}
}
}
}
بعد إرسال المحتوى، ينهي الامتداد عمله باستدعاء completeRequest — هذه خطوة إلزامية؛ بدونها لن يحرر النظام عملية الامتداد. مهم: يعمل Share Extension في بيئة محدودة مع وصول مقيد للشبكة ونظام الملفات — استخدم جلسات خلفية لرفع المحتوى.
يجب على Share Extension معالجة أنواع مختلفة من بيانات الإدخال بشكل صحيح: النصوص والصور والفيديو والروابط والملفات. كل نوع يستخدم UTI الخاص به وطريقة استخراج خاصة. المعالجة الشاملة — بالتكرار عبر attachment.attachments مع فحوصات hasItemConformingToTypeIdentifier.
تُمرر الصور كـ public.image مع إمكانية الحصول عليها عبر UIImage أو Data. للصور الكبيرة، استخدم jpegData(compressionQuality:) قبل الحفظ. لا يجب على Share Extension تعديل الصورة الأصلية دون إذن صريح من المستخدم. يُوصى بحفظ الأصل في App Group وإنشاء معاينة للعرض في الواجهة.
يمرر Safari والمتصفحات الأخرى الروابط كـ public.url والنص المحدد كـ public.plain-text. يمكن أن تحتوي حاوية NSExtensionItem واحدة على كلا النوعين في وقت واحد — رابط الصفحة والنص المحدد فيها. يجب على Share Extension فحص جميع المرفقات واستخراج البيانات ذات الصلة. السيناريو المدمج: حفظ الرابط كإشارة مرجعية والنص كملاحظة مرفقة به.
يعمل Share Extension والتطبيق الرئيسي في عمليات مختلفة ولا يشتركان في الوصول إلى نظام الملفات. يستخدم تبادل البيانات آلية App Groups: حاوية مشتركة بمعرّف group.*. بعد حفظ البيانات في App Group، يُعلم الامتداد التطبيق عبر CFNotificationCenter أو Darwin Notify.
تُفعّل App Groups في إمكانيات الهدف: اختر App Groups وأضف معرّفاً (مثلاً، group.com.example.myapp). يجب أن يكون لكل من الهدفين — التطبيق الرئيسي والامتداد — وصول إلى نفس المجموعة. مجموعة UserDefaults تسمح بقراءة وكتابة البيانات في التخزين المشترك بأقل حمل إضافي.
// حفظ البيانات في App Group من Share Extension
let sharedDefaults = UserDefaults(suiteName: "group.com.example.myapp")
let bookmark: [String: Any] = [
"url": url.absoluteString,
"title": contentText ?? "",
"date": Date().timeIntervalSince1970
]
sharedDefaults?.set(bookmark, forKey: "bookmark_\(Date().timeIntervalSince1970)")
sharedDefaults?.synchronize()
الأسئلة الشائعة
Share Extension يستقبل المحتوى من التطبيقات الأخرى إلى تطبيقك. أما Action Extension فينفذ إجراءً على المحتوى داخل التطبيق المضيف — ترجمة نص، تعديل صورة. Share Extension استقبال، Action Extension تحويل.
يعتمد ذلك على نوع المحتوى الذي يعالجه تطبيقك. للإشارات المرجعية — public.url. لتحرير الصور — public.image. للملاحظات — public.plain-text. لأنواع متعددة، استخدم NSExtensionActivationRule مع مجموعة من المسندات AND/OR.
سبب شائع هو قاعدة NSExtensionActivationRule غير صحيحة أو عدم تطابق UTI. تحقق في Info.plist: يجب أن تطابق قاعدة التفعيل نوع المحتوى المختبر. أيضاً تأكد من أن الامتداد مفعل في الإعدادات → تطبيقك → Siri والبحث. Xcode clean build غالباً ما يحل المشكلة.
يخصص النظام حوالي 30 ثانية للتنفيذ. بعد ذلك، ينهي iOS عملية الامتداد قسراً. للعمليات الطويلة، استخدم NSURLSession في الخلفية وتعامل مع النتيجة عند بدء التشغيل التالي للتطبيق.
نعم، بدلاً من SLComposeServiceViewController يمكنك استخدام UIViewController عادي. في هذه الحالة، تتحكم بالواجهة بالكامل. لكن يجب تنفيذ أزرار الإرسال والإلغاء بنفسك. الواجهة المخصصة موصى بها للسيناريوهات غير القياسية لمعالجة المحتوى.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.