إضافات iOS في كوردوفا

من موسوعة حسوب
< Cordova
مراجعة 21:19، 22 نوفمبر 2018 بواسطة محمد-بغات (نقاش | مساهمات) (أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:إضافات iOS في كوردوفا}}</noinclude> تصنيف: Cordova تصنيف: plugins ios تصنيف: ios يقدم هذ...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث

 يقدم هذا القسم تفاصيل عن كيفية تقديم (implement) شيفرات الإضافات الأصلية (native plugin code) على منصة iOS. قبل قراءة هذه الصفحة، راجع صفحة دليل تطوير الإضافات [../../hybrid/plugins/index.html Plugin Development Guide] للحصول على نظرة عامة على بنية الإضافات وواجهة [[JavaScript|جافااسكريبت]] الخاصة بها. يستمر هذا القسم في تطوير مثال الإضافة echo الوارد في دليل تطوير الإضافات، والذي يتواصل بين المعرض webview الخاص بكوردوفا وبين المنصة الأصلية.

يتم تقديم (implement) إضافات iOS على هيئة صنف من لغة ‏‎ ‏‎Objective-C‎‎، والذي يوسع الصنف CDVPlugin. لكي يُربط الوسيط exec المعطى للتابع service في [[JavaScript|جافااسكريبت]] مع صنف في لغة Objective-C، فيجب تسجيل كل كل أصناف الإضافة على هيئة وسم <feature> في الملف config.xml.

إعداد صنف الإضافة

يستخدم جزء [[JavaScript|جافااسكريبت]] من الإضافة التابع cordova.exec على النحو التالي:

exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);

هذا يرسل طلبية (request) من UIWebView إلى الجانب الأصلي (native side) من منصة iOS، ويستدعي التابع action على الصنف service فعلياً، مع تمرير الوسائط المعطاة في المصفوفة args.

قم بحديد الإضافة على هيئة وسم <feature> في الملف config.xml الخاص بتطبيق Cordova-iOS، مع استخدام الملف plugin.xml لإدراج هذا الوسم تلقائيًا، كما هو موضح في [../../hybrid/plugins/index.html Plugin Development Guide]:

<feature name="LocalStorage">
    <param name="ios-package" value="CDVLocalStorage" />
</feature>‎

يجب أن تتطابق الخاصية name في الوسم feature مع قيمة الوسيط exec الذي مررته سابقا إلى دالة [[JavaScript|جافااسكريبت]] service. كما يجب أن تتطابق الخاصية value مع اسم صنف Objective-C في الإضافة. يجب أن تساوي الخاصية <param> في الوسم name دائمًا القيمة ios-package. إذا لم تتبع هذه الإرشادات، فقد يتم تصريف (compile) الإضافة، ولكن قد لا تتمكن كوردوفا من الوصول إليه.

تهيئة الإضافات ودورة الحياة (Plugin Initialization and Lifetime)

يتم إنشاء نسخة (instance) واحدة من كائن الإضافة خلال دورة حياة المعرض UIWebView. لا يتم إنشاء نسخ للإضافات حتى تتم الإشارة إليها أولاً عبر استدعاء من [[JavaScript|جافااسكريبت]]، إلا في حال إضافة وسم <param> مع خاصية onload مساوية للقيمة name، إلى "true" في config.xml. فمثلا،

<feature name="Echo">
    <param name="ios-package" value="Echo" />
    <param name="onload" value="true" />
</feature>‎

يجب أن تستخدم الإضافات التابع pluginInitialize في مرحلة الانطلاق.

لإضافات ذات الطلبيات الطويلة (long-running requests)، أو النشاطات الخلفية (background activity)، مثل قارئات الوسائط، أو المستمعات (listeners)، أو النشاطات ذات الحالة الداخلية (internal state) يجب أن تقدِّم (implement) التابع onReset لإلغاء تلك الطلبيات الطويلة، أو للتنظيفه بعد تلك الأنشطة. يتم تشغيل التابع عند انتقال UIWebView إلى صفحة جديدة/ أو عند تحديث الصفحة، وهو ما يؤدي إلى إعادة تحميل [[JavaScript|جافااسكريبت]].

كتابة إضافات iOS

يرسل استدعاء من [[JavaScript|جافااسكريبت]] طلبية إضافة (plugin request) إلى الجانب الأصلي (native side)، ويُعيّن إضافة Objective-C المقابلة في الملف config.xml. أي شيء يتم إرساله إلى الإضافة عبر دالة [[JavaScript|جافااسكريبت]] exec سيُمرّر إلى التابع action الخاص بصنف بالإضافة. فيما يلي إمضاء (signature) تابع الإضافة:

- (void)myMethod:(CDVInvokedUrlCommand*)command
{
    CDVPluginResult* pluginResult = nil;
    NSString* myarg = [command.arguments objectAtIndex:0];
    if (myarg != nil) {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
    } else {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Arg was null"];
    }
    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

لمزيد من التفاصيل، راجع الصفحات CDVInvokedUrlCommand.h و CDVPluginResult.h و CDVCommandDelegate.h.

أنواع الرسائل CDVPluginResult في المنصة iOS

يمكنك استخدام CDVPluginResult لإعادة مجموعة متنوعة من أنواع النتائج إلى استدعاءات [[JavaScript|جافااسكريبت]]، باستخدام توابع الصنف التي تتبع هذا النمط:

+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...

يمكنك إنشاء الأنواع String و Int و Double و Bool و Array و Dictionary و ArrayBuffer و Multipart. يمكنك أيضًا استبعاد أي وسيط لإرسال حالة، أو لإعادة خطأ، أو يمكن حتى اختيار عدم إرسال أي نتيجة للإضافة، وفي هذه الحالة لن يُطلق أيٌّ من تلك الاستدعاءات.

تذكر ما يلي للتعامل مع القيم المعادة المعقدة:

messageAsArrayBuffer تتوقع NSData*، وتحول إلى ArrayBuffer في استدعاء [[JavaScript|جافااسكريبت]]. وبالمثل، أي كائن ArrayBuffer ترسله [[JavaScript|جافااسكريبت]] إلى الإضافة سيُحوّل إلى NSData*.

messageAsMultipart تتوقع مصفوفة NSArray* تحتوي على أي من الأنواع المدعومة الأخرى، وترسل المصفوفة بأكملها باعتبارها arguments إلى استدعاء [[JavaScript|جافااسكريبت]] (JavaScript callback). بهذه الطريقة، تُسلسل (serialized) كل الوسائط أو تُفلّ (deserialized) بحسب الضرورة، لذلك من الآمن إعادة NSData* كسلسلة متعددة (multipart)، ولكن ليس على هيئة مصفوة أو قاموس Array / Dictionary.

مثال لإضافة iOS

لمطابقة ميزة [[JavaScript|جافااسكريبت]] echo المقدمة في واجهة [[JavaScript|جافااسكريبت]] في صفحة الإضافات، استخدم الملف plugin.xml لإدراج مواصفات feature في الملف config.xml الخاص بالمنصة المحلية:

<platform name="ios">
    <config-file target="config.xml" parent="/*">
        <feature name="Echo">
            <param name="ios-package" value="Echo" />
        </feature>
    </config-file>
</platform>‎

ثم نضيف الملفين Echo.h و Echo.m إلى المجلد Plugins الموجود في مجلد تطبيق Cordova-iOS:

/********* Echo.h Cordova Plugin Header *******/
#import <Cordova/CDVPlugin.h>

@interface Echo : CDVPlugin
- (void)echo:(CDVInvokedUrlCommand*)command;
@end
/********* Echo.m Cordova Plugin Implementation *******/
#import "Echo.h"
#import <Cordova/CDVPlugin.h>

@implementation Echo
- (void)echo:(CDVInvokedUrlCommand*)command
{
    CDVPluginResult* pluginResult = nil;
    NSString* echo = [command.arguments objectAtIndex:0];
    if (echo != nil && [echo length] > 0) {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
    } else {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
    }
    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
@end

تُوسّع عمليات الاستيراد في الجزء العلوي من الملف الصنف من CDVPlugin. في هذه الحالة، لا تدعم الإضافة سوى إجراء (action) واحد echo. تستخلص السلسلة النصية المعروضة echo عن طريق استدعاء التابع objectAtIndex للحصول على الوسيط الأول الموجود في المصفوفة arguments، والذي يتوافق مع الوسائط المُمررة بواسطة دالة [[JavaScript|جافااسكريبت]] exec().

يتحقق من الوسيط للتأكد من أنها لا يساوي القيمة nil أو سلسلة نصية فارغة، ثم يعيد PluginResult مع الحالة ERROR إذا كان الأمر كذلك. إذا اجتاز الوسيط الفحص، فسيُعاد PluginResult مع حالة تساوي OK، وتمرر إلى السلسلة النصية الأصلية echo. وأخيرًا، يرسل النتيجة إلى التابع self.commandDelegate، والذي ينفذ دوال النجاح أو الإخفاق (success or failure callbacks) الخاصة بالتابع exec على جانب [[JavaScript|جافااسكريبت]]. في حال استدعاء دالة النجاح، فسيُمرر إليها الوسيط echo.

التكامل مع منصة iOS

يوفر الصنف CDVPlugin توابع أخرى يمكن أن تعيد الإضافة الخاصة بك تعريفها. على سبيل المثال، يمكنك إمساك الأحداث [../../../cordova/events/events.html#pause pause] و [../../../cordova/events/events.html#resume resume] و إنهاء التطبيق (app terminate) و handleOpenURL. راجع الصنفين CDVPlugin.h و CDVPlugin.m لأجل الإرشادات.

المهام الفرعية (Threading)

تنفّذ توابع الإضافة عادةً في نفس المهمة الفرعية التي تشتغل عليها الواجهة الرئيسية. إن كانت الإضافة تتطلب قدرًا كبيرًا من المعالجة، أو تتطلب القيام باستدعاء مُعطل (blocking call)، فعليك استخدام مهمة فرعية خلفية. مثلا:

- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
{
    // Check command.arguments here.
    [self.commandDelegate runInBackground:^{
        NSString* payload = nil;
        // Some blocking logic...
        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
        // The sendPluginResult method is thread-safe.
        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }];
}

تصحيح إضافات iOS ‏ (Debugging iOS Plugins‏)

لتصحيح الأخطاء من جانب شيفرة Objective-C، سيكون عليك استخدام المصحح المدمج Xcode. بالنسبة إلى [[JavaScript|جافااسكريبت]]، يمكنك ربط Safari بالتطبيق المُشتغل في جعاز أو محاكي iOS.

أخطاء شائعة

لا تنسَ إضافة خريطة الإضافة (plugin's mapping) إلى config.xml. وإن نسيت، سيُسجّل خطأ في وحدة تحكم Xcode.

لا تنس إضافة كل المضيفات التي تتصل بها في القائمة البيضاء، كما هو موضح في صفحة [../../appdev/whitelist/index.html Whitelist Guide]. وإن نسيت، فسيُسجّل خطأ في وحدة تحكم Xcode.

مصادر