الفرق بين المراجعتين لصفحة: «Cordova/plugins ios»

من موسوعة حسوب
أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE:إضافات iOS في كوردوفا}}</noinclude> تصنيف: Cordova تصنيف: plugins ios تصنيف: ios يقدم هذ...'
 
تحديث
 
(5 مراجعات متوسطة بواسطة مستخدمين اثنين آخرين غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:إضافات iOS في كوردوفا}}</noinclude>
<noinclude>{{DISPLAYTITLE:تطوير الإضافات على منصة iOS في كوردوفا}}</noinclude>
[[تصنيف: Cordova]]
[[تصنيف: Cordova]]
[[تصنيف: plugins ios]]
[[تصنيف: Cordova Plugin]]
[[تصنيف: ios]]
يقدم هذا القسم تفاصيل عن كيفية تنفيذ شيفرات الإضافات الأصلية (native plugin code) على منصة iOS. قبل قراءة هذه الصفحة، راجع صفحة [[Cordova/plugins|دليل تطوير الإضافات]] للحصول على نظرة عامة على بنية الإضافات وواجهة [[JavaScript|JavaScript]] الخاصة بها.  
يقدم هذا القسم تفاصيل عن كيفية تقديم (implement) شيفرات الإضافات الأصلية (native plugin code) على منصة iOS. قبل قراءة هذه الصفحة، راجع صفحة دليل تطوير الإضافات [../../hybrid/plugins/index.html  Plugin Development Guide] للحصول على نظرة عامة على بنية الإضافات وواجهة [[JavaScript|[[Java|جافا]]اسكريبت]] الخاصة بها. يستمر هذا القسم في تطوير مثال الإضافة echo الوارد في دليل تطوير الإضافات، والذي يتواصل بين المعرض [[Cordova/webviews|webview]] الخاص بكوردوفا وبين المنصة الأصلية.  


يتم تقديم (implement) إضافات iOS على هيئة صنف من لغة ‏‎ ‏‎Objective-C‎‎، والذي يوسع الصنف <code>CDVPlugin</code>. لكي يُربط الوسيط <code>exec</code> المعطى للتابع <code>service</code> في [[JavaScript|[[Java|جافا]]اسكريبت]] مع صنف في لغة Objective-C، فيجب تسجيل كل كل أصناف الإضافة على هيئة وسم <code><feature></code> في الملف <code>config.xml</code>.  
يواصل هذا القسم تطوير مثال [[Cordova/plugins#.D9.85.D8.AB.D8.A7.D9.84 JavaScript|الإضافة echo]] الوارد في دليل تطوير الإضافات، والذي يربط الاتصال بين المعرض [[Cordova/webviews|webview]] والمنصة الأصلية (native platform).


== إعداد صنف الإضافة ==
يتم تنفيذ إضافات iOS على هيئة صنف من لغة ‏‎ ‏‎Objective-C‎‎، والذي يوسع الصنف <code>CDVPlugin</code>.


يستخدم جزء [[JavaScript|[[Java|جافا]]اسكريبت]] من الإضافة التابع <code>cordova.exec</code> على النحو التالي:  
لكي يُربط المعامل <code>service</code> المُمرر إلى التابع <code>exec</code> الذي يخص [[JavaScript]] مع صنف في لغة Objective-C، فيجب تسجيل كل أصناف الإضافة على هيئة وسم <code><feature></code> في الملف <code>config.xml</code>.
<syntaxhighlight lang="javascript">exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);‎</syntaxhighlight>  
==إعداد صنف الإضافة==
يُستخدم الجزء من الإضافة المكتوب بلغة [[JavaScript|JavaScript]] التابعَ <code>cordova.exec</code> على النحو التالي:<syntaxhighlight lang="objective-c">exec(<successFunction>, <failFunction>, <service>, <action>, [<args>]);‎</syntaxhighlight>هذا سيُرسل طلبية (request) من <code>UIWebView</code> إلى الجانب الأصلي (native side) من منصة iOS، ثم يستدعي التابع <code>action</code> على الصنف <code>service</code> فعليًا، مع تمرير الوسائط المعطاة في المصفوفة <code>args</code>.


هذا يرسل طلبية (request) من <code>UIWebView</code> إلى الجانب الأصلي (native side) من منصة iOS، ويستدعي التابع <code>action</code> على الصنف <code>service</code> فعلياً، مع تمرير الوسائط المعطاة في المصفوفة <code>args</code>.
حدِّد الإضافة على هيئة وسم <code><feature></code> في الملف <code>config.xml</code> الخاص بتطبيق Cordova-iOS، مع استخدام الملف <code>plugin.xml</code> لإدراج هذا الوسم تلقائيًا، كما هو موضح في [[Cordova/plugins|دليل تطوير الإضافات]]:<syntaxhighlight lang="xml"><feature name="LocalStorage">
 
قم بحديد الإضافة على هيئة وسم <code><feature></code> في الملف <code>config.xml</code> الخاص بتطبيق Cordova-iOS، مع استخدام الملف <code>plugin.xml</code> لإدراج هذا الوسم تلقائيًا، كما هو موضح في [../../hybrid/plugins/index.html  Plugin Development Guide]:  
<syntaxhighlight lang="javascript"><feature name="LocalStorage">
     <param name="ios-package" value="CDVLocalStorage" />
     <param name="ios-package" value="CDVLocalStorage" />
</feature>‎</syntaxhighlight>  
</feature>‎</syntaxhighlight>يجب أن تتطابق الخاصية <code>name</code> في الوسم <code>feature</code> مع قيمة المعامل <code>service</code> الذي مررته سابقا إلى الدالة <code>exec</code> التي تخص [[JavaScript|JavaScript]]. كما يجب أن تتطابق الخاصية <code>value</code> مع اسم صنف الإضافة في Objective-C. ويجب أن تساوي الخاصية <code>name</code> في الوسم <code><param></code> دائمًا القيمة "<code>ios-package"</code>.
 
يجب أن تتطابق الخاصية <code>name</code> في الوسم feature مع قيمة الوسيط <code>exec</code> الذي مررته سابقا إلى دالة [[JavaScript|[[Java|جافا]]اسكريبت]] <code>service</code>. كما يجب أن تتطابق الخاصية <code>value</code> مع اسم صنف Objective-C في الإضافة. يجب أن تساوي الخاصية <code><param></code> في الوسم <code>name</code> دائمًا القيمة <code>ios-package</code>. إذا لم تتبع هذه الإرشادات، فقد يتم تصريف (compile) الإضافة، ولكن قد لا تتمكن كوردوفا من الوصول إليه.
 
== تهيئة الإضافات ودورة الحياة (Plugin Initialization and Lifetime) ==


يتم إنشاء نسخة (instance) واحدة من كائن الإضافة خلال دورة حياة المعرض <code>UIWebView</code>. لا يتم إنشاء نسخ للإضافات حتى تتم الإشارة إليها أولاً عبر استدعاء من [[JavaScript|[[Java|جافا]]اسكريبت]]، إلا في حال إضافة وسم <code><param></code> مع خاصية <code>onload</code> مساوية للقيمة <code>name</code>، إلى <code>"true"</code> في <code>config.xml</code>. فمثلا،
إذا لم تتبع هذه الإرشادات، فقد يتم تصريف (compile) الإضافة، ولكن قد لا تتمكن كوردوفا من الوصول إليها.
<syntaxhighlight lang="javascript"><feature name="Echo">
==تهيئة ودورة الحياة الإضافات==
يتم إنشاء نسخة (instance) واحدة من كائن الإضافة خلال دورة حياة (lifetime) المعرض <code>UIWebView</code>. لا يتم إنشاء نسخ للإضافات حتى تتم الإشارة إليها أولًا عبر استدعاء من [[JavaScript|JavaScript]]، إلا في حال إضافة الوسم <code><param></code> مع الخاصيتين <code>name="onload"‎</code> و <code>value="true"</code>في الملف <code>config.xml</code> على النحو التالي:<syntaxhighlight lang="xml"><feature name="Echo">
     <param name="ios-package" value="Echo" />
     <param name="ios-package" value="Echo" />
     <param name="onload" value="true" />
     <param name="onload" value="true" />
</feature>‎</syntaxhighlight>  
</feature>‎</syntaxhighlight>يجب أن تستخدم الإضافاتُ التابع <code>pluginInitialize</code> في مرحلة الانطلاق (startup logic).


يجب أن تستخدم الإضافات التابع <code>pluginInitialize</code> في مرحلة الانطلاق.  
لإضافات الطلبيات الطويلة (long-running requests)، أو النشاطات الخلفية (background activity)، مثل قارئات الوسائط، أو المستمعات (listeners)، أو النشاطات ذات الحالة الداخلية (internal state)، يجب أن تنفِّذ التابع <code>onReset</code> لأجل إلغاء تلك الطلبيات الطويلة، أو للتنظيف بعد تلك الأنشطة. يتم تشغيل التابع <code>onReset</code> عند انتقال <code>UIWebView</code> إلى صفحة جديدة أو عند تحديث الصفحة، وهو ما يؤدي إلى إعادة تحميل [[JavaScript|JavaScript]].
==كتابة إضافات iOS==
يرسل استدعاء [[JavaScript|JavaScript]] طلبية إضافة (plugin request) إلى الجانب الأصلي (native side)، وتُعيّن إضافة Objective-C المقابلة في الملف <code>config.xml</code>. وأي شيء يتم إرساله إلى الإضافة عبر الدالة <code>exec</code> سيُمرّر إلى التابع <code>action</code> الخاص بصنف بالإضافة.


لإضافات ذات الطلبيات الطويلة (long-running requests)، أو النشاطات الخلفية (background activity)، مثل قارئات الوسائط، أو المستمعات (listeners)، أو النشاطات ذات الحالة الداخلية (internal state) يجب أن تقدِّم (implement) التابع <code>onReset</code> لإلغاء تلك الطلبيات الطويلة، أو للتنظيفه بعد تلك الأنشطة. يتم تشغيل التابع عند انتقال <code>UIWebView</code> إلى صفحة جديدة/ أو عند تحديث الصفحة، وهو ما يؤدي إلى إعادة تحميل [[JavaScript|[[Java|جافا]]اسكريبت]].
فيما يلي توقيع (signature) تابع الإضافة:<syntaxhighlight lang="objective-c">- (void)myMethod:(CDVInvokedUrlCommand*)command
 
== كتابة إضافات iOS ==
 
يرسل استدعاء من [[JavaScript|[[Java|جافا]]اسكريبت]] طلبية إضافة (plugin request) إلى الجانب الأصلي (native side)، ويُعيّن إضافة Objective-C المقابلة في الملف <code>config.xml</code>. أي شيء يتم إرساله إلى الإضافة عبر دالة [[JavaScript|[[Java|جافا]]اسكريبت]] <code>exec</code> سيُمرّر إلى التابع <code>action</code> الخاص بصنف بالإضافة. فيما يلي إمضاء (signature) تابع الإضافة:  
<syntaxhighlight lang="javascript">- (void)myMethod:(CDVInvokedUrlCommand*)command
{
{
     CDVPluginResult* pluginResult = nil;
     CDVPluginResult* pluginResult = nil;
     NSString* myarg = [command.arguments objectAtIndex:0];
     NSString* myarg = [command.arguments objectAtIndex:0];
     if (myarg != nil) {
     if (myarg != nil) {
         pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
         pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
سطر 46: سطر 38:
     }
     }
     [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}</syntaxhighlight>  
}</syntaxhighlight>لمزيد من التفاصيل، اطلع على الصفحات [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h CDVInvokedUrlCommand.h] و [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPluginResult.h CDVPluginResult.h] و [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVCommandDelegate.h CDVCommandDelegate.h].
 
==أنواع الرسائل CDVPluginResult في منصة iOS==
لمزيد من التفاصيل، راجع الصفحات [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVInvokedUrlCommand.h CDVInvokedUrlCommand.h] و [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPluginResult.h CDVPluginResult.h] و [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVCommandDelegate.h CDVCommandDelegate.h].  
يمكنك استخدام <code>CDVPluginResult</code> لإعادة مجموعة متنوعة من أنواع النتائج إلى استدعاءات [[JavaScript|JavaScript]]، باستخدام توابع تتبع النمط التالي:<syntaxhighlight lang="objective-c">+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...‎</syntaxhighlight>يمكنك إنشاء الأنواع <code>String</code> و <code>Int</code> و <code>Double</code> و <code>Bool</code> و <code>Array</code> و <code>Dictionary</code> و <code>ArrayBuffer</code> و <code>Multipart</code>. يمكنك أيضًا استبعاد أي وسيط لأجل إرسال حالة، أو لإعادة خطأ، أو يمكنك حتى اختيار عدم إرسال أي نتيجة للإضافة، وفي هذه الحالة لن يُطلق أيٌّ من تلك الاستدعاءات.
 
== أنواع الرسائل CDVPluginResult في المنصة iOS ==  
 
يمكنك استخدام <code>CDVPluginResult</code> لإعادة مجموعة متنوعة من أنواع النتائج إلى استدعاءات [[JavaScript|[[Java|جافا]]اسكريبت]]، باستخدام توابع الصنف التي تتبع هذا النمط:  
<syntaxhighlight lang="javascript">+ (CDVPluginResult*)resultWithStatus:(CDVCommandStatus)statusOrdinal messageAs...‎</syntaxhighlight>  
 
يمكنك إنشاء الأنواع <code>String</code> و <code>Int</code> و <code>Double</code> و <code>Bool</code> و <code>Array</code> و <code>Dictionary</code> و <code>ArrayBuffer</code> و <code>Multipart</code>. يمكنك أيضًا استبعاد أي وسيط لإرسال حالة، أو لإعادة خطأ، أو يمكن حتى اختيار عدم إرسال أي نتيجة للإضافة، وفي هذه الحالة لن يُطلق أيٌّ من تلك الاستدعاءات.  


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


<code>messageAsArrayBuffer</code> تتوقع <code>NSData*</code>، وتحول إلى <code>ArrayBuffer</code> في استدعاء [[JavaScript|[[Java|جافا]]اسكريبت]]. وبالمثل، أي كائن <code>ArrayBuffer</code> ترسله [[JavaScript|[[Java|جافا]]اسكريبت]] إلى الإضافة سيُحوّل إلى <code>NSData*</code>.
==الإضافة echo مثالًا لإضافة iOS==
 
لمطابقة واجهة [[Cordova/plugins#.D9.85.D8.AB.D8.A7.D9.84 JavaScript|الميزة echo]] المقدمة في صفحة [[Cordova/plugins|الإضافات]]، استخدم الملف <code>plugin.xml</code> لإدراج مواصفات <code>feature</code> في الملف <code>config.xml</code> الخاص بالمنصة المحلية:<syntaxhighlight lang="xml"><platform name="ios">
<code>messageAsMultipart</code> تتوقع مصفوفة <code>NSArray*</code> تحتوي على أي من الأنواع المدعومة الأخرى، وترسل المصفوفة بأكملها باعتبارها <code>arguments</code> إلى استدعاء [[JavaScript|[[Java|جافا]]اسكريبت]] (JavaScript callback). بهذه الطريقة، تُسلسل (serialized) كل الوسائط أو تُفلّ (deserialized) بحسب الضرورة، لذلك من الآمن إعادة <code>NSData*</code> كسلسلة متعددة (multipart)، ولكن ليس على هيئة مصفوة أو قاموس <code>Array</code> / <code>Dictionary</code>.
 
== مثال لإضافة iOS ==  
 
لمطابقة ميزة [[JavaScript|[[Java|جافا]]اسكريبت]] echo المقدمة في واجهة [[JavaScript|[[Java|جافا]]اسكريبت]] في صفحة الإضافات، استخدم الملف <code>plugin.xml</code> لإدراج مواصفات <code>feature</code> في الملف <code>config.xml</code> الخاص بالمنصة المحلية:  
<syntaxhighlight lang="javascript"><platform name="ios">
     <config-file target="config.xml" parent="/*">
     <config-file target="config.xml" parent="/*">
         <feature name="Echo">
         <feature name="Echo">
سطر 72: سطر 53:
         </feature>
         </feature>
     </config-file>
     </config-file>
</platform></syntaxhighlight>  
</platform></syntaxhighlight>ثم أضف الملفين <code>Echo.h</code> و <code>Echo.m</code> إلى المجلد <code>Plugins</code> الموجود في مجلد تطبيق Cordova-iOS:<syntaxhighlight lang="objective-c">/********* Echo.h Cordova Plugin Header *******/


ثم نضيف الملفين <code>Echo.h</code> و <code>Echo.m</code> إلى المجلد <code>Plugins</code> الموجود في مجلد تطبيق Cordova-iOS:
<syntaxhighlight lang="javascript">/********* Echo.h Cordova Plugin Header *******/
#import <Cordova/CDVPlugin.h>
#import <Cordova/CDVPlugin.h>


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


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


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


يتحقق من الوسيط للتأكد من أنها لا يساوي القيمة <code>nil</code> أو سلسلة نصية فارغة، ثم يعيد <code>PluginResult</code> مع الحالة <code>ERROR</code> إذا كان الأمر كذلك. إذا اجتاز الوسيط الفحص، فسيُعاد <code>PluginResult</code> مع حالة تساوي <code>OK</code>، وتمرر إلى السلسلة النصية الأصلية <code>echo</code>. وأخيرًا، يرسل النتيجة إلى التابع <code>self.commandDelegate</code>، والذي ينفذ دوال النجاح أو الإخفاق (success or failure callbacks) الخاصة بالتابع <code>exec</code> على جانب [[JavaScript|[[Java|جافا]]اسكريبت]]. في حال استدعاء دالة النجاح، فسيُمرر إليها الوسيط <code>echo</code>.  
تتحقق الشيفرة من أن المعامل لا يساوي القيمة <code>nil</code> أو سلسلة نصية فارغة؛ فإن كان الأمر كذلك، فستعيد <code>PluginResult</code> مع الحالة "<code>ERROR</code>" وإلا فستعيد <code>PluginResult</code> مع الحالة "<code>OK</code>"، مع تمرير السلسلة النصية الأصلية <code>echo</code>. وأخيرًا، تُرسل النتيجة إلى التابع <code>self.commandDelegate</code>، والذي ينفذ دوال ردود نداء النجاح أو الفشل (success or failure callbacks) الخاصة بالتابع <code>exec</code> على جانب [[JavaScript|JavaScript]]. في حال استدعاء دالة رد نداء النجاح، فسيُمرر إليها المعامل <code>echo</code>.
 
==التكامل مع منصة iOS==
== التكامل مع منصة iOS ==  
يوفر الصنف <code>CDVPlugin</code> توابع أخرى يمكن إعادة تعريفها من قبل الإضافة. على سبيل المثال، يمكنك إمساك الأحداث <code>[https://cordova.apache.org/docs/en/latest/cordova/events/events.html#pause pause]</code> و <code>[https://cordova.apache.org/docs/en/latest/cordova/events/events.html#resume resume]</code> وإنهاء التطبيق (app terminate) و <code>handleOpenURL</code>. ألقِ نظرةً على الصنفين [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPlugin.h CDVPlugin.h] و [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPlugin.m CDVPlugin.m] للمزيد من الإرشادات.
 
==المهام الفرعية==
يوفر الصنف <code>CDVPlugin</code> توابع أخرى يمكن أن تعيد الإضافة الخاصة بك تعريفها. على سبيل المثال، يمكنك إمساك الأحداث [../../../cordova/events/events.html#pause pause] و [../../../cordova/events/events.html#resume resume] و إنهاء التطبيق (app terminate) و <code>handleOpenURL</code>. راجع الصنفين [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPlugin.h CDVPlugin.h] و [https://github.com/apache/cordova-ios/blob/master/CordovaLib/Classes/Public/CDVPlugin.m CDVPlugin.m] لأجل الإرشادات.  
تنفّذ توابع الإضافة عادةً في نفس المهمة الفرعية (thread) التي تشتغل عليها الواجهة الرئيسية. إن كانت الإضافة تتطلب قدرًا كبيرًا من المعالجة، أو تتطلب القيام باستدعاء مُعطِّل (blocking call)، فعليك استخدام مهمة فرعية خلفية (background thread). اطلع على الشيفرة التالي مثلًا:<syntaxhighlight lang="objective-c">- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
 
== المهام الفرعية (Threading) ==  
 
تنفّذ توابع الإضافة عادةً في نفس المهمة الفرعية التي تشتغل عليها الواجهة الرئيسية. إن كانت الإضافة تتطلب قدرًا كبيرًا من المعالجة، أو تتطلب القيام باستدعاء مُعطل (blocking call)، فعليك استخدام مهمة فرعية خلفية. مثلا:  
<syntaxhighlight lang="javascript">- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
{
{
     // Check command.arguments here.
     // هنا command.arguments تحقق من
     [self.commandDelegate runInBackground:^{
     [self.commandDelegate runInBackground:^{
         NSString* payload = nil;
         NSString* payload = nil;
         // Some blocking logic...
         // Some blocking logic...
         CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
         CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
         // The sendPluginResult method is thread-safe.
         // آمن في المهام الفرعية sendPluginResult استخدام
         [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
         [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
     }];
     }];
}‎</syntaxhighlight>  
}‎</syntaxhighlight>
 
==تنقيح إضافات iOS==
== تصحيح إضافات iOS ‏ (Debugging iOS Plugins‏) ==  
لتنقيح (debug) الأخطاء في شيفرة Objective-C، سيكون عليك استخدام المُصحِّح المدمج في Xcode. أما بالنسبة إلى [[JavaScript|JavaScript]]، فيمكنك ربط Safari بالتطبيق عبر محاكي أو جهاز  iOS.
 
==أخطاء شائعة==
لتصحيح الأخطاء من جانب شيفرة Objective-C، سيكون عليك استخدام المصحح المدمج Xcode. بالنسبة إلى [[JavaScript|[[Java|جافا]]اسكريبت]]، يمكنك ربط Safari بالتطبيق المُشتغل في جعاز أو محاكي iOS.  
* لا تنسَ إدراج خريطة الإضافة (plugin's mapping) إلى الملف <code>config.xml</code>. وإلا فسيُسجّل خطأ في وحدة تحكم Xcode.
 
* لا تنسَ إضافة كل المضيفات التي تتصل بها في [[Cordova/whitelist|القائمة البيضاء]]. وإلا فسيُسجّل خطأ في وحدة تحكم Xcode.
== أخطاء شائعة ==  


لا تنسَ إضافة خريطة الإضافة (plugin's mapping) إلى <code>config.xml</code>. وإن نسيت، سيُسجّل خطأ في وحدة تحكم Xcode.
== انظر أيضًا==
*[[Cordova/plugins android|إضافات أندرويد]]
*[[Cordova/plugins windows|إضافات ويندوز]]


لا تنس إضافة كل المضيفات التي تتصل بها في القائمة البيضاء، كما هو موضح في صفحة [../../appdev/whitelist/index.html  Whitelist Guide]. وإن نسيت، فسيُسجّل خطأ في وحدة تحكم Xcode.
*[[Cordova/plugins|دليل تطوير الإضافات]]
==مصادر==
==مصادر==
*[https://cordova.apache.org/docs/en/latest/guide/platforms/ios/plugin.html قسم إضافات iOS في التوثيق الرسمي لكوردوفا.]
*[https://cordova.apache.org/docs/en/latest/guide/platforms/ios/plugin.html صفحة iOS Plugin Development Guide في توثيق كوردوفا الرسمي.]

المراجعة الحالية بتاريخ 11:12، 1 ديسمبر 2020

يقدم هذا القسم تفاصيل عن كيفية تنفيذ شيفرات الإضافات الأصلية (native plugin code) على منصة iOS. قبل قراءة هذه الصفحة، راجع صفحة دليل تطوير الإضافات للحصول على نظرة عامة على بنية الإضافات وواجهة JavaScript الخاصة بها.

يواصل هذا القسم تطوير مثال الإضافة echo الوارد في دليل تطوير الإضافات، والذي يربط الاتصال بين المعرض webview والمنصة الأصلية (native platform).

يتم تنفيذ إضافات iOS على هيئة صنف من لغة ‏‎ ‏‎Objective-C‎‎، والذي يوسع الصنف CDVPlugin.

لكي يُربط المعامل service المُمرر إلى التابع exec الذي يخص 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 لإدراج هذا الوسم تلقائيًا، كما هو موضح في دليل تطوير الإضافات:

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

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

إذا لم تتبع هذه الإرشادات، فقد يتم تصريف (compile) الإضافة، ولكن قد لا تتمكن كوردوفا من الوصول إليها.

تهيئة ودورة الحياة الإضافات

يتم إنشاء نسخة (instance) واحدة من كائن الإضافة خلال دورة حياة (lifetime) المعرض UIWebView. لا يتم إنشاء نسخ للإضافات حتى تتم الإشارة إليها أولًا عبر استدعاء من JavaScript، إلا في حال إضافة الوسم <param> مع الخاصيتين name="onload"‎ و value="true"‎في الملف config.xml على النحو التالي:

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

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

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

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

يرسل استدعاء JavaScript طلبية إضافة (plugin request) إلى الجانب الأصلي (native side)، وتُعيّن إضافة Objective-C المقابلة في الملف config.xml. وأي شيء يتم إرساله إلى الإضافة عبر الدالة 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 في استدعاء جافاسكريبت. وبالمثل، أي كائن ArrayBuffer ترسله JavaScript إلى الإضافة سيُحوّل إلى NSData*‎.
  • messageAsMultipart تتوقع مصفوفة NSArray*‎ تحتوي على أيٍّ من الأنواع المدعومة الأخرى، وترسل المصفوفة بأكملها باعتبارها الوسيط arguments إلى رد نداء JavaScript. بهذه الطريقة، تُسلسل (serialized) كل الوسائط أو تُفك (deserialized) بحسب الضرورة، لذلك من الآمن إعادة NSData*‎ كسلسلة متعددة (multipart)، ولكن ليس على هيئة مصفوفة أو قاموس.

الإضافة echo مثالًا لإضافة iOS

لمطابقة واجهة الميزة echo المقدمة في صفحة الإضافات، استخدم الملف 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

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

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

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

يوفر الصنف CDVPlugin توابع أخرى يمكن إعادة تعريفها من قبل الإضافة. على سبيل المثال، يمكنك إمساك الأحداث pause و resume وإنهاء التطبيق (app terminate) و handleOpenURL. ألقِ نظرةً على الصنفين CDVPlugin.h و CDVPlugin.m للمزيد من الإرشادات.

المهام الفرعية

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

- (void)myPluginMethod:(CDVInvokedUrlCommand*)command
{
    // هنا command.arguments تحقق من
    [self.commandDelegate runInBackground:^{
        NSString* payload = nil;
        // Some blocking logic...
        CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
        // آمن في المهام الفرعية sendPluginResult  استخدام
        [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
    }];
}

تنقيح إضافات iOS

لتنقيح (debug) الأخطاء في شيفرة Objective-C، سيكون عليك استخدام المُصحِّح المدمج في Xcode. أما بالنسبة إلى JavaScript، فيمكنك ربط Safari بالتطبيق عبر محاكي أو جهاز iOS.

أخطاء شائعة

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

 انظر أيضًا

مصادر