يعرب المصطفى

Members
  • عدد منشوراتي

    7
  • تاريخ الإنضمام

  • تاريخ اخر زياره

السمعه بالموقع

3 Neutral

عن العضو يعرب المصطفى

  • الرتبه
    مبدع جديد
  1. اللغة المستخدمة : swift3 البرنامج : xcode 8 السلام عليكم، في هذا الدرس سنتحدث عن واحدة من أهم المهارات التي تساعدك في بناء مشروعك في وقت قياسي و بنتائج ممتازة اعتمادا على استخدام مكتبات قام بإنشائها مطورون آخرون لتكون متاحة لجميع المطورين. لكن قبل ذلك علينا فهم بعض الأمور الأساسية للبدء ثم سنتحدث عن طريقة تنزيل المكتبات إلى مشاريعك. الTermianl : حتى تستطيع التعامل مع الملفات الخارجية يجب أن تتعلم في البداية طريقة التعامل مع الterminal Terminal : هي واجهة غير رسومية يمكن استخدامها لتنفيذ الأوامر العادية التي تقوم بها كإنشاء ملف أو حذفه.. الخ. للوصول إليها كل ما عليك فعله هو كتابة terminal في شريط البحث للوصول السريع إليها و ستظهر لك كأول نتيجة، قم بفتحها كما ذكرنا فإن الterminal هي واجهة غير رسومية يمكن فيها تنفيذ الأوامر عن طريق كتابتها بطريقة معينة و إهم الإوامر التي يجب التعرف عليها لهذا الدرس هي التالية : cd : و هي اختصار ل (change directory ) و هي تستخدم للانتقال إلى أحد المجلدات و هي تشبه فتحك لأي مجلد من المجلدات بالطريقة العادية. ls : و هي تستخدم لعرض كل محتويات المجلد الموجود بداخله حاليا. الآن قم بفتح الterminal و قم بكتابة : cd Desktop للانتقال إلى سطح المكتب الخاص بك الآن قم بكتابة ls لتظهر محتويات سطح المكتب. ستجد أن كل الملفات و المجلدات و التطبيقات الموجودة في سطح المكتب قد تم عرضها لك في الterminal. هذه أهم الأمور التي يجب معرفتها فيما يخص وحدة التحكم أو الterminal للمواصلة في هذا الدرس. الCocoapod : و الآن حتى تتمكن من تنزيل المكتبات و الحصول عليها لابد من تنزيل أداة على وحدة التحكم للحصول على إمكانية استخدام أوامر مهمة تمكنك من إضافة المكتبات مباشرة في مشاريعك في الxcode و هذه الأداة تسمى cocoa pod و حتى تقوم بتنزيلها على الterminal الخاص بك قم بزيارة موقعهم: https://cocoapods.org/ و انسخ السطر الموجود في خانة Install أو انسخه مباشرة من هنا : sudo gem install cocoapods و قم بلصقه في وحدة التحكم (terminal) لديك. قد يطلب منك إدخال رقمك سري، قم بإدخاله ثم اضغط زر return أو enter. حينها سيبدأ الterminal بتنزيل الcocoa pod. ملاحظة: قد لا تظهر لك أي إشارة في الterminal تشير إلى أن البرنامج يتم تنزيله حاليا، و لكن يمكنك التأكد إذا ما نظرت إلى الزر الأحمر في الزاوية اليسرى في الشريط العلوي و الخاص بإغلاق البرنامج. حيث يفترض أن تجد بداخله دائرة سوداء و التي تشير إلى أن البرنامج يقوم بتنفيذ أحد العمليات في الوقت الحالي كما في الصورة التالية... الآن بعد اكتمال التنزيل ستزول النقطة السوداء و ستظهر لك مجموعة من التعليمات تخبرك باكتمال التنزيل كما في الصورة التالية: الآن يمكنك أن تتعامل مع المكتبات الموجودة و تنزيلها إلى مشروعك. تنزيل المكتبات في الجزء التالي من الدرس سنقوم بتنزيل إحدى المكتبات على مشروع xcode و سنختار JTAppleCalendar و هي تستخدم لإنشاء تقويم و استخدامه في مشروعك، و لكن لن نتحدث عن طريقة إنشاء التقويم و التعامل معه و إنما الغرض شرح طريقة تنزيل المكتبات على مشروعك و استخدام الcocoa pod لذلك يمكنك اختيار أي خيار آخر لتنزيله. و الاختيارات يمكن الوصول إليها من عدة مصادر أهمها و أشهرها الgithup حيث يمكنك البحث هناك عن كل ما تريد. و هنا رابط المكتبة التي سنقوم بتنزيلها إلى المشروع : https://github.com/patchthecode/JTAppleCalendar إذا لنبدأ.. في البداية قم بإنشاء مشروع xcode جديد و سمه demo مثلا و قم بحفظه على سطح المكتب. -- صورة الآن قم بفتح الterminal.. نريد في البداية الوصول إلى موقع المجلد الذي يحوي كل ملفات المشروع لتنزيل المكتبة في ذلك المكان و لذلك يجب علينا استخدام أمر cd ثم إضافة المسار الخاص بالمشروع للوصول إليه من خلال الterminal. ولكن يمكن استخدام طريقة أسهل من عمل ذلك يدويا و هي : ١- قم بكتابة cd ثم مسافة ٢- قم بسحب المجلد من سطح المكتب و أفلته في الterminal و ستجد أن الterminal قام بإضافة مسار المجلد تلقائيا ٣- اضغط enter أو return الآن تم الوصول إلى داخل المجلد و يمكنك التأكد من ذلك عن طريق استعراض الملفات بداخل المجلد بالضغط على ls و ستجد أن الterminal يعرض لك ملفات المشروع الخاصة بك. الآن قم بكتابة الأمر التالي على الterminal : pod init ثم اضغط enter - هذا الأمر خاص بإنشاء ملف باسم pod file و هو الملف الذي يجب أن يحوي كل المكتبات التي تريد استخدامها في مشروعك. و للتأكد من أن الملف قد تم إنشاؤه قم بإدخال أمر ls مرة أخرى و يجب عليك أن تجد ملف جديد باسم Podfile أو يمكنك فتح المجلد يدويا و ستجد ذلك الملف بالداخل. - الآن قم بفتح ملف الpodfile حيث سنقوم بإضافة بعض الأسطر بداخله. - الآن عليك إضافة أسماء المكتبات التي ستقوم باستخدامها داخل هذا الملف. لكن من أين نحصل على اسم المكتبات ؟ عليك دائما أن تعود إلى التوجيهات المكتوبة من مصدر التنزيل ذاته للحصول على هذه المعلومات، لذلك قم بالعودة إلى الرابط مرة أخرى https://github.com/patchthecode/JTAppleCalendar دائما عند تنزيل المكتبات لابد من البحث على خانة الinstallation بطريقة الcocoa pod لذلك توجه إلى خانة installiation via cocoa pod و ستجد أنه يشير إلى أمر تنزيل الcocoa pod حيث قمنا بذلك مسبقا. و بعد ذلك يريك المحتويات التي يجب أن تكون بداخل ملف الPodFile لذلك انسخ منها الأشياء التي لا يحويها الملف الموجود عندك و هي التالية : source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks! و هذه التعليمات في الأعلى ضعها في بداية الملف pod 'JTAppleCalendar', '~> 7.0' و هذه ضعها بدلا من : #Pods for demo أخيرا ملف الpodFile يجب أن يبدو كالتالي : # Uncomment the next line to define a global platform for your project source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks! target 'demo' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! pod 'JTAppleCalendar', '~> 7.0' target 'demoTests' do inherit! :search_paths # Pods for testing end target 'demoUITests' do inherit! :search_paths # Pods for testing end end مع ملاحظة النقاط التالية : ١- أي سطر يبدأ ب# فهو كالcomment في البرمجة لا تأثير له و لذلك لا مشكلة في حال وجود سطور إضافية من هذا النوع في ملفي أو ملفك. ٢- لا مشكلة إذا لم يكن ملفك يحوي السطور التالية : target 'demoTests' do inherit! :search_paths # Pods for testing end target 'demoUITests' do inherit! :search_paths # Pods for testing end ٣- قد يكون هناك اختلاف في الاسم إذا لم تقم بتسمية مشروعك باسم demo و لا مشكلة في ذلك. - الآن أصبح ملف الpodfile جاهزا كل ما عليك فعله هو حفظ التغييرات التي قمت بإجرائها عليه ثم إغلاقه. - الآن تبقت خطوة أخيرة.. قم بالعودة للterminal و تأكد أنك ما زلت في مسار المشروع و قم بإدخال : pod install و اضغط enter سيبدأ الآن الterminal بتحميل المكتبات التي طلبتها و عندما يكتمل التحميل سيشعرك بذلك كما في الصورة.. الآن اذهب إلى ملف الxcode الذي كنت تعمل به و قم بإغلاقه ثم توجه إلى مجلد المشروع الخاص بك و ستجد أن هناك ملف xcode جديد ظهر لديك في المجلد.. حيث أن هذا هو نفس مشروعك الذي كنت تعمل به و لكن الفرق الوحيد أنه يضم كل المكتبات التي طلبت تنزيلها. و الآن لتتأكد أن التنزيل تم بطريقة صحيحة.. قم بفتح الملف الجديد و اذهب إلى أي كلاس و في أعلا الملف قم بكتابة أمر : import JTAppleCalender إذا لم يظهر البرنامج أي مشكلة فهذا يعني أنك قمت بتضمين المكتبة في مشروعك بنجاح. ملاحظة : قد يظهر الxcode خطأ في البداية عند كتابتك لهذا الأمر.. حينها قم بمسحه و قم بعمل build عن طريق cmd+b ثم اكتب الأمر مرة أخرى و يجب أن يعمل هذه المرة إلى هنا نصل إلى نهاية الدرس و إن كنت تود تجربة عمل الcalender و استخدام المكتبة فقم بمتابعة الفيديوهات الموجودة في رابط تنزيل المكتبة و قراءة التوجيهات الموجودة هناك. إلى اللقاء في دروس قريبة قادمة بإذن الله
  2. اللغة المستخدمة : swift3 البرنامج : xcode 8 السلام عليكم، في هذا الدرس سنتحدث عن واحدة من أهم المهارات التي تساعدك في بناء مشروعك في وقت قياسي و بنتائج ممتازة اعتمادا على استخدام مكتبات قام بإنشائها مطورون آخرون لتكون متاحة لجميع المطورين. لكن قبل ذلك علينا فهم بعض الأمور الأساسية للبدء ثم سنتحدث عن طريقة تنزيل المكتبات إلى مشاريعك. الTermianl : حتى تستطيع التعامل مع الملفات الخارجية يجب أن تتعلم في البداية طريقة التعامل مع الterminal Terminal : هي واجهة غير رسومية يمكن استخدامها لتنفيذ الأوامر العادية التي تقوم بها كإنشاء ملف أو حذفه.. الخ. للوصول إليها كل ما عليك فعله هو كتابة terminal في شريط البحث للوصول السريع إليها و ستظهر لك كأول نتيجة، قم بفتحها كما ذكرنا فإن الterminal هي واجهة غير رسومية يمكن فيها تنفيذ الأوامر عن طريق كتابتها بطريقة معينة و إهم الإوامر التي يجب التعرف عليها لهذا الدرس هي التالية : cd : و هي اختصار ل (change directory ) و هي تستخدم للانتقال إلى أحد المجلدات و هي تشبه فتحك لأي مجلد من المجلدات بالطريقة العادية. ls : و هي تستخدم لعرض كل محتويات المجلد الموجود بداخله حاليا. الآن قم بفتح الterminal و قم بكتابة : cd Desktop للانتقال إلى سطح المكتب الخاص بك الآن قم بكتابة ls لتظهر محتويات سطح المكتب. ستجد أن كل الملفات و المجلدات و التطبيقات الموجودة في سطح المكتب قد تم عرضها لك في الterminal. هذه أهم الأمور التي يجب معرفتها فيما يخص وحدة التحكم أو الterminal للمواصلة في هذا الدرس. الCocoapod : و الآن حتى تتمكن من تنزيل المكتبات و الحصول عليها لابد من تنزيل أداة على وحدة التحكم للحصول على إمكانية استخدام أوامر مهمة تمكنك من إضافة المكتبات مباشرة في مشاريعك في الxcode و هذه الأداة تسمى cocoa pod و حتى تقوم بتنزيلها على الterminal الخاص بك قم بزيارة موقعهم: https://cocoapods.org/ و انسخ السطر الموجود في خانة Install أو انسخه مباشرة من هنا : sudo gem install cocoapods و قم بلصقه في وحدة التحكم (terminal) لديك. قد يطلب منك إدخال رقمك سري، قم بإدخاله ثم اضغط زر return أو enter. حينها سيبدأ الterminal بتنزيل الcocoa pod. ملاحظة: قد لا تظهر لك أي إشارة في الterminal تشير إلى أن البرنامج يتم تنزيله حاليا، و لكن يمكنك التأكد إذا ما نظرت إلى الزر الأحمر في الزاوية اليسرى في الشريط العلوي و الخاص بإغلاق البرنامج. حيث يفترض أن تجد بداخله دائرة سوداء و التي تشير إلى أن البرنامج يقوم بتنفيذ أحد العمليات في الوقت الحالي كما في الصورة التالية... الآن بعد اكتمال التنزيل ستزول النقطة السوداء و ستظهر لك مجموعة من التعليمات تخبرك باكتمال التنزيل كما في الصورة التالية: الآن يمكنك أن تتعامل مع المكتبات الموجودة و تنزيلها إلى مشروعك. تنزيل المكتبات في الجزء التالي من الدرس سنقوم بتنزيل إحدى المكتبات على مشروع xcode و سنختار JTAppleCalendar و هي تستخدم لإنشاء تقويم و استخدامه في مشروعك، و لكن لن نتحدث عن طريقة إنشاء التقويم و التعامل معه و إنما الغرض شرح طريقة تنزيل المكتبات على مشروعك و استخدام الcocoa pod لذلك يمكنك اختيار أي خيار آخر لتنزيله. و الاختيارات يمكن الوصول إليها من عدة مصادر أهمها و أشهرها الgithup حيث يمكنك البحث هناك عن كل ما تريد. و هنا رابط المكتبة التي سنقوم بتنزيلها إلى المشروع : https://github.com/patchthecode/JTAppleCalendar إذا لنبدأ.. في البداية قم بإنشاء مشروع xcode جديد و سمه demo مثلا و قم بحفظه على سطح المكتب. -- صورة الآن قم بفتح الterminal.. نريد في البداية الوصول إلى موقع المجلد الذي يحوي كل ملفات المشروع لتنزيل المكتبة في ذلك المكان و لذلك يجب علينا استخدام أمر cd ثم إضافة المسار الخاص بالمشروع للوصول إليه من خلال الterminal. ولكن يمكن استخدام طريقة أسهل من عمل ذلك يدويا و هي : ١- قم بكتابة cd ثم مسافة ٢- قم بسحب المجلد من سطح المكتب و أفلته في الterminal و ستجد أن الterminal قام بإضافة مسار المجلد تلقائيا ٣- اضغط enter أو return الآن تم الوصول إلى داخل المجلد و يمكنك التأكد من ذلك عن طريق استعراض الملفات بداخل المجلد بالضغط على ls و ستجد أن الterminal يعرض لك ملفات المشروع الخاصة بك. الآن قم بكتابة الأمر التالي على الterminal : pod init ثم اضغط enter - هذا الأمر خاص بإنشاء ملف باسم pod file و هو الملف الذي يجب أن يحوي كل المكتبات التي تريد استخدامها في مشروعك. و للتأكد من أن الملف قد تم إنشاؤه قم بإدخال أمر ls مرة أخرى و يجب عليك أن تجد ملف جديد باسم Podfile أو يمكنك فتح المجلد يدويا و ستجد ذلك الملف بالداخل. - الآن قم بفتح ملف الpodfile حيث سنقوم بإضافة بعض الأسطر بداخله. - الآن عليك إضافة أسماء المكتبات التي ستقوم باستخدامها داخل هذا الملف. لكن من أين نحصل على اسم المكتبات ؟ عليك دائما أن تعود إلى التوجيهات المكتوبة من مصدر التنزيل ذاته للحصول على هذه المعلومات، لذلك قم بالعودة إلى الرابط مرة أخرى https://github.com/patchthecode/JTAppleCalendar دائما عند تنزيل المكتبات لابد من البحث على خانة الinstallation بطريقة الcocoa pod لذلك توجه إلى خانة installiation via cocoa pod و ستجد أنه يشير إلى أمر تنزيل الcocoa pod حيث قمنا بذلك مسبقا. و بعد ذلك يريك المحتويات التي يجب أن تكون بداخل ملف الPodFile لذلك انسخ منها الأشياء التي لا يحويها الملف الموجود عندك و هي التالية : source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks! و هذه التعليمات في الأعلى ضعها في بداية الملف pod 'JTAppleCalendar', '~> 7.0' و هذه ضعها بدلا من : #Pods for demo أخيرا ملف الpodFile يجب أن يبدو كالتالي : # Uncomment the next line to define a global platform for your project source 'https://github.com/CocoaPods/Specs.git' platform :ios, '10.0' use_frameworks! target 'demo' do # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! pod 'JTAppleCalendar', '~> 7.0' target 'demoTests' do inherit! :search_paths # Pods for testing end target 'demoUITests' do inherit! :search_paths # Pods for testing end end مع ملاحظة النقاط التالية : ١- أي سطر يبدأ ب# فهو كالcomment في البرمجة لا تأثير له و لذلك لا مشكلة في حال وجود سطور إضافية من هذا النوع في ملفي أو ملفك. ٢- لا مشكلة إذا لم يكن ملفك يحوي السطور التالية : target 'demoTests' do inherit! :search_paths # Pods for testing end target 'demoUITests' do inherit! :search_paths # Pods for testing end ٣- قد يكون هناك اختلاف في الاسم إذا لم تقم بتسمية مشروعك باسم demo و لا مشكلة في ذلك. - الآن أصبح ملف الpodfile جاهزا كل ما عليك فعله هو حفظ التغييرات التي قمت بإجرائها عليه ثم إغلاقه. - الآن تبقت خطوة أخيرة.. قم بالعودة للterminal و تأكد أنك ما زلت في مسار المشروع و قم بإدخال : pod install و اضغط enter سيبدأ الآن الterminal بتحميل المكتبات التي طلبتها و عندما يكتمل التحميل سيشعرك بذلك كما في الصورة.. الآن اذهب إلى ملف الxcode الذي كنت تعمل به و قم بإغلاقه ثم توجه إلى مجلد المشروع الخاص بك و ستجد أن هناك ملف xcode جديد ظهر لديك في المجلد.. حيث أن هذا هو نفس مشروعك الذي كنت تعمل به و لكن الفرق الوحيد أنه يضم كل المكتبات التي طلبت تنزيلها. و الآن لتتأكد أن التنزيل تم بطريقة صحيحة.. قم بفتح الملف الجديد و اذهب إلى أي كلاس و في أعلا الملف قم بكتابة أمر : import JTAppleCalender إذا لم يظهر البرنامج أي مشكلة فهذا يعني أنك قمت بتضمين المكتبة في مشروعك بنجاح. ملاحظة : قد يظهر الxcode خطأ في البداية عند كتابتك لهذا الأمر.. حينها قم بمسحه و قم بعمل build عن طريق cmd+b ثم اكتب الأمر مرة أخرى و يجب أن يعمل هذه المرة إلى هنا نصل إلى نهاية الدرس و إن كنت تود تجربة عمل الcalender و استخدام المكتبة فقم بمتابعة الفيديوهات الموجودة في رابط تنزيل المكتبة و قراءة التوجيهات الموجودة هناك. إلى اللقاء في دروس قريبة قادمة بإذن الله
  3. البرنامج المستخدم : xcode8 اللغة المستخدمة : swift3 السلام عليكم.. في هذا الدرس سنتكلم عن الoptional في لغة سويفت. ماهي؟ و كيف و تستخدم ؟ و لماذا ؟ و للتطبيق على هذا الدرس لن تحتاج سوى للplayground و لن تحتاج لإنشاء مشروع جديد.. لذلك قم بفتح برنامج الإكس كود و قم باختيار : get started with a playground ما هو الoptional ؟ لنتعرف أكثر على ماهية الoptional قم بإضافة السطر التالي إلى الplayground : var x : Int = 5 لقد قمت بتعريف متغير باسم x و من نوع Int و قمت بإسناد القيمة 5 إليه.. لكن هل أنت بحاجة لإسناد قيمة للمتغير بمجرد إنشائه ؟ ماذا إن كنت لاتريد وضع قيمة ابتدائية للمتغير ؟ ماذا إن كنت غير متأكد من أن المتغير x يجب أن يحوي قيمة أصلا؟؟ مثلا: تخيل أنك تقوم بعمل موقع و حتى يقوم المستخدم بالتسجيل فيه عليه أن يضيف بياناته، هناك بعض البيانات المهمة التي يجب أن يضعها المستخدم كالاسم و الإيميل.. الخ لكن لنفرض أن أحد هذه البيانات هو رقم الجوال، عادة و في أغلب المواقع رقم الجوال ليس إجباريا و يمكن للمستخدم أن يضعه باختياره، و بالتالي أن كانت القيمة x تمثل رقم الجوال فليس من الضروري أن تحوي قيمة فبعض المستخدمين سيقومون بإضافتها و الآخرون لا.. و هنا تكمن أهمية الoptional حيث تتيح فرصة للمتغير أن يحوي قيمة معينة أو أن يكون بلا قيمة ( تكون له قيمة nil ) الآن عد إلى الكود الذي كتبته و جرب أن تمسح القيمة التي أسندتها للمتغير ليبدو بهذا الشكل : var x : Int ثم قم بكتابة x السطر الذي يليه لتعرض قيمتها على الشريط الجانبي ستجد أن البرنامج يعرض لك خطأ نصه : variable 'x' used before being initialized و هذا يعني أن المتغير x يتم استخدامه قبل أن يتم إنشاء قيمة خاصة فيه حيث أن من شروط لغة سويفت في أي متغير هو أن يحوي قيمة قبل أن يتم استخدامه أصلا لذا لابد من وجود قيمة تعني عدم وجود قيمة للمتغير كحل لهذه الحالة و يمكن استبدال هذا القيمة مستقبلا بقيمة من نوع المتغير ( Int في هذه الحالة ) لعل الأمور تبدو معقدة بعض الشيء لكن ستتضح مع إكمال الدرس.. أحد القيم التي يمكن إسنادها للمتغيرات بأنواعها المختلفة هي قيمة nil و التي تعني ( لا شيء ) و هي التي تقابلها null في لغات أخرى كالجافا مثلا و هذه القيمة تكمن أهميتها في: -أنها تعطي قيمة ابتدائية للمتغير و بالتالي يمكن استخدام المتغير دون أخطاء. -أن هذه القيمة هي ليست Int و لا String و لا Double... الخ بل هي قيمة مميزة تعطينا إشارة أن المتغير الذي يحملها لا يحوي قيمة. - أن هذه القيمة يمكن استبدالها مستقبلا بقيمة أخرى حسب نوع المتغير. الآن قم بتحويل تعريف المتغير x ليبدو كالتالي : var x : Int = nil لاحظ أن البرنامج سيظهر لك خطأ مرة أخرى لكن لمَ هذا الخطأ ؟ ألم نذكر أن هذه القيمة يمكن أن يحويها متغير من أي نوع ؟ إذا مالمشكلة ؟ صحيح أن أي متغير من أي نوع يمكن أن يحوي هذه القيمة، و لكن لن تكون له إمكانية الحصول على هذه القيمة إلا عندما تعطيه هذه الإمكانية عند تعريف هذا المتغير بإضافة (؟) بجانب نوعه عند تعريفه ليبدو كالتالي.. var x : Int? = nil و الآن يمكنك أن تطلق على المتغير x اسم optional و هي تعني اختياري أي بمعنى آخر : لك الخيار في تحديد ما إذا كان الx يساوي قيمة حقيقية من نوع Int أو لا يحوي قيمة أصلا( يساوي nil ) و هذا بفضل علامة الاستفهام التي قمنا بإضافتها بجانب المتغير. و الآن نوع المتغير x لم يعد Int و إنما أصبح Int? أو optional Int و يمكنك التأكد من النوع عن طريق الضغط على alt و اسم المتغير وسيظهر لك نوعه و الآن: قم بتغيير x إلى قيمة 5 مثلا في السطر الذي يليه ثم إلى قيمة nil في السطر الذي يليه ثم إلى قيمة 10 مثلا و لاحظ أن ذلك يتم دون مشاكل و دون أخطاء x = 5 x = nil x = 10 x = nil و الآن قم بجعل x = أحد قيم الint و لتكن ١٠ على سبيل المثال ثم قم بطباعة قيمة المتغير x x = 10 print(x) لاحظ أن البرنامج لم يقم بطباعة قيمة x و إنما قام بطباعتها بداخل كلمة Optional بالشكل التالي : Optional(10) صحيح أن x هي الآن تساوي القيمة ١٠ لكنها ما زالت قيمة من optinal Int و ما زال طابع الoptional يغطي هذا المتغير و حتى تقوم بتخليصها من غطاء الoptional الذي يحويها يمكنك أن تستخدم ما يعرف ب : force unwrapping و هو تخليص المتغير من غطاء الoptional في مرحلة معينة أو في سطر محدد من البرنامج و ذلك عن طريق استخدام علامة التعجب بجانب اسم المتغير، قم بالرجوع إلى أمر الطباعة و قم بكتابته بإضافة علامة التعجب للمتغير كالتالي : print(x!) الآن بخلاف المرة السابقة سيقوم البرنامج بطباعة 10. لماذا؟ لأنك قمت برفع غطاء الoptional من x و هو ما يعرف بال(unwrapping) فأصبحت تحوي قيمة (Int) بدلا من (Int?) أو (optional Int) فأصبحت كمتغير Int عادي في هذا السطر من الكود. إن رفع الغطاء الذي قمت بعمله لن يطبق على x إلا في ذلك السطر و أما في باقي السطور فأن x ستبقى optional Int. جرب أن تطبع x في السطر التالي لتتأكد من ذلك و الآن لنفرض أنك ستقوم باستخدام x عدة مرات خلال برنامجك و في كل هذه المرات لا تريد أن تعامل x معاملة الoptional بل تريد أن تقوم بعمل unwrapping لها في كل مرة دون أي استثناء فمالحل ؟ قبل الإجابة قد تتساءل: مالفائدة من جعل x لتكون optional عند تعريفها إذا كنا سنرفع عنها غطاء الoptional في كل مرة نستخدمها فيه في الكود ؟ و الإجابة على ذلك: قد تحتاج في بعض الحالات إلى البدء بقيمة nil للx في البداية فقط و لكن بعد ذلك ستكون متأكدا أن الx لن تساوي nil أبدا بعد هذه المرحلة و لذلك ستحتاج لعمل unwrapping في كل مرة. أو لتفادي عمل unwrapping و كتابة ! في كل مرة يمكنك استخدام علامة التعجب عند تعريف المتغير كالتالي : var x : Int! = nil و هي تعني : أن المتغير x سيكون optional و سيساوي nil في البداية و لكن متى ما تم استخدامه فسيرفع عنه غطاء الoptional و سيعامل كمتغير Int يحوي قيمة دون الحاجة لكتابة علامة التعجب. و للتأكد من ذلك قم بإسناد قيمة لx و من ثم قيم بطباعة القيمة x = 4 print(x) و ستجد أن البرنامج يقوم بطباعة 4 دون ظهور كلمة optional في الحقيقة.. إن استخدام رفع الغطاء عن متغيرات الoptional بهذه الطريقة يعتبر طريقة سيئة و خطيرة في كتابة الكود و سنوضح خطر كتابة الكود بهذه الطريقة و الحل المستخدم لتفادي ذلك في الدرس القادم باذن الله إلى ذلك الحين استودعكم الله
  4. البرنامج المستخدم : xcode8 اللغة المستخدمة : swift3 السلام عليكم.. في هذا الدرس سنتكلم عن الoptional في لغة سويفت. ماهي؟ و كيف و تستخدم ؟ و لماذا ؟ و للتطبيق على هذا الدرس لن تحتاج سوى للplayground و لن تحتاج لإنشاء مشروع جديد.. لذلك قم بفتح برنامج الإكس كود و قم باختيار : get started with a playground ما هو الoptional ؟ لنتعرف أكثر على ماهية الoptional قم بإضافة السطر التالي إلى الplayground : var x : Int = 5 لقد قمت بتعريف متغير باسم x و من نوع Int و قمت بإسناد القيمة 5 إليه.. لكن هل أنت بحاجة لإسناد قيمة للمتغير بمجرد إنشائه ؟ ماذا إن كنت لاتريد وضع قيمة ابتدائية للمتغير ؟ ماذا إن كنت غير متأكد من أن المتغير x يجب أن يحوي قيمة أصلا؟؟ مثلا: تخيل أنك تقوم بعمل موقع و حتى يقوم المستخدم بالتسجيل فيه عليه أن يضيف بياناته، هناك بعض البيانات المهمة التي يجب أن يضعها المستخدم كالاسم و الإيميل.. الخ لكن لنفرض أن أحد هذه البيانات هو رقم الجوال، عادة و في أغلب المواقع رقم الجوال ليس إجباريا و يمكن للمستخدم أن يضعه باختياره، و بالتالي أن كانت القيمة x تمثل رقم الجوال فليس من الضروري أن تحوي قيمة فبعض المستخدمين سيقومون بإضافتها و الآخرون لا.. و هنا تكمن أهمية الoptional حيث تتيح فرصة للمتغير أن يحوي قيمة معينة أو أن يكون بلا قيمة ( تكون له قيمة nil ) الآن عد إلى الكود الذي كتبته و جرب أن تمسح القيمة التي أسندتها للمتغير ليبدو بهذا الشكل : var x : Int ثم قم بكتابة x السطر الذي يليه لتعرض قيمتها على الشريط الجانبي ستجد أن البرنامج يعرض لك خطأ نصه : variable 'x' used before being initialized و هذا يعني أن المتغير x يتم استخدامه قبل أن يتم إنشاء قيمة خاصة فيه حيث أن من شروط لغة سويفت في أي متغير هو أن يحوي قيمة قبل أن يتم استخدامه أصلا لذا لابد من وجود قيمة تعني عدم وجود قيمة للمتغير كحل لهذه الحالة و يمكن استبدال هذا القيمة مستقبلا بقيمة من نوع المتغير ( Int في هذه الحالة ) لعل الأمور تبدو معقدة بعض الشيء لكن ستتضح مع إكمال الدرس.. أحد القيم التي يمكن إسنادها للمتغيرات بأنواعها المختلفة هي قيمة nil و التي تعني ( لا شيء ) و هي التي تقابلها null في لغات أخرى كالجافا مثلا و هذه القيمة تكمن أهميتها في: -أنها تعطي قيمة ابتدائية للمتغير و بالتالي يمكن استخدام المتغير دون أخطاء. -أن هذه القيمة هي ليست Int و لا String و لا Double... الخ بل هي قيمة مميزة تعطينا إشارة أن المتغير الذي يحملها لا يحوي قيمة. - أن هذه القيمة يمكن استبدالها مستقبلا بقيمة أخرى حسب نوع المتغير. الآن قم بتحويل تعريف المتغير x ليبدو كالتالي : var x : Int = nil لاحظ أن البرنامج سيظهر لك خطأ مرة أخرى لكن لمَ هذا الخطأ ؟ ألم نذكر أن هذه القيمة يمكن أن يحويها متغير من أي نوع ؟ إذا مالمشكلة ؟ صحيح أن أي متغير من أي نوع يمكن أن يحوي هذه القيمة، و لكن لن تكون له إمكانية الحصول على هذه القيمة إلا عندما تعطيه هذه الإمكانية عند تعريف هذا المتغير بإضافة (؟) بجانب نوعه عند تعريفه ليبدو كالتالي.. var x : Int? = nil و الآن يمكنك أن تطلق على المتغير x اسم optional و هي تعني اختياري أي بمعنى آخر : لك الخيار في تحديد ما إذا كان الx يساوي قيمة حقيقية من نوع Int أو لا يحوي قيمة أصلا( يساوي nil ) و هذا بفضل علامة الاستفهام التي قمنا بإضافتها بجانب المتغير. و الآن نوع المتغير x لم يعد Int و إنما أصبح Int? أو optional Int و يمكنك التأكد من النوع عن طريق الضغط على alt و اسم المتغير وسيظهر لك نوعه و الآن: قم بتغيير x إلى قيمة 5 مثلا في السطر الذي يليه ثم إلى قيمة nil في السطر الذي يليه ثم إلى قيمة 10 مثلا و لاحظ أن ذلك يتم دون مشاكل و دون أخطاء x = 5 x = nil x = 10 x = nil و الآن قم بجعل x = أحد قيم الint و لتكن ١٠ على سبيل المثال ثم قم بطباعة قيمة المتغير x x = 10 print(x) لاحظ أن البرنامج لم يقم بطباعة قيمة x و إنما قام بطباعتها بداخل كلمة Optional بالشكل التالي : Optional(10) صحيح أن x هي الآن تساوي القيمة ١٠ لكنها ما زالت قيمة من optinal Int و ما زال طابع الoptional يغطي هذا المتغير و حتى تقوم بتخليصها من غطاء الoptional الذي يحويها يمكنك أن تستخدم ما يعرف ب : force unwrapping و هو تخليص المتغير من غطاء الoptional في مرحلة معينة أو في سطر محدد من البرنامج و ذلك عن طريق استخدام علامة التعجب بجانب اسم المتغير، قم بالرجوع إلى أمر الطباعة و قم بكتابته بإضافة علامة التعجب للمتغير كالتالي : print(x!) الآن بخلاف المرة السابقة سيقوم البرنامج بطباعة 10. لماذا؟ لأنك قمت برفع غطاء الoptional من x و هو ما يعرف بال(unwrapping) فأصبحت تحوي قيمة (Int) بدلا من (Int?) أو (optional Int) فأصبحت كمتغير Int عادي في هذا السطر من الكود. إن رفع الغطاء الذي قمت بعمله لن يطبق على x إلا في ذلك السطر و أما في باقي السطور فأن x ستبقى optional Int. جرب أن تطبع x في السطر التالي لتتأكد من ذلك و الآن لنفرض أنك ستقوم باستخدام x عدة مرات خلال برنامجك و في كل هذه المرات لا تريد أن تعامل x معاملة الoptional بل تريد أن تقوم بعمل unwrapping لها في كل مرة دون أي استثناء فمالحل ؟ قبل الإجابة قد تتساءل: مالفائدة من جعل x لتكون optional عند تعريفها إذا كنا سنرفع عنها غطاء الoptional في كل مرة نستخدمها فيه في الكود ؟ و الإجابة على ذلك: قد تحتاج في بعض الحالات إلى البدء بقيمة nil للx في البداية فقط و لكن بعد ذلك ستكون متأكدا أن الx لن تساوي nil أبدا بعد هذه المرحلة و لذلك ستحتاج لعمل unwrapping في كل مرة. أو لتفادي عمل unwrapping و كتابة ! في كل مرة يمكنك استخدام علامة التعجب عند تعريف المتغير كالتالي : var x : Int! = nil و هي تعني : أن المتغير x سيكون optional و سيساوي nil في البداية و لكن متى ما تم استخدامه فسيرفع عنه غطاء الoptional و سيعامل كمتغير Int يحوي قيمة دون الحاجة لكتابة علامة التعجب. و للتأكد من ذلك قم بإسناد قيمة لx و من ثم قيم بطباعة القيمة x = 4 print(x) و ستجد أن البرنامج يقوم بطباعة 4 دون ظهور كلمة optional في الحقيقة.. إن استخدام رفع الغطاء عن متغيرات الoptional بهذه الطريقة يعتبر طريقة سيئة و خطيرة في كتابة الكود و سنوضح خطر كتابة الكود بهذه الطريقة و الحل المستخدم لتفادي ذلك في الدرس القادم باذن الله إلى ذلك الحين استودعكم الله
  5. البرنامج المستخدم : xcode 8 اللغة المستخدمة : swift 3 هذا الدرس هو الجزء الثاني من درس الtableview مع الـ Swift إذا كنت لم تشاهد الجزء الأول فقم بمشاهدته الآن من خلال الرابط التالي : في الدرس السابق وصلنا في النهاية إلى هذه النتيجة.. و هي تمثل جدول أو tableview يحوي أسماء الطلاب، و في هذا الدرس سنقوم بتطوير هذا الجدول و تحسينه ليحوي بيانات أكثر عن كل طالب و بالشكل الذي تختاره أنت كمطور. إذا لنبدأ.. الآن إضافةً لعرض أسماء الطلاب نريد عرض بيانات خاصة بهم كالعمر و رقم الجوال و سنقوم بعرض هذه البيانات في الجدول. و بالتالي فأن كل طالب سيكون له ٣ بيانات مختلفة متصلة به و خاصة به و هي الاسم و العمر و رقم الجوال بدلا من الاسم وحده. و بالتالي كيف يمكن أن نربط مجموعة من البيانات لشيء واحد فقط ؟ لو عدنا إلى الarray التي تمثل مصدر البيانات أو الdata source للtableview و التي تحمل اسم students فسنجد أنها تحتوي على أسماء الطلاب فقط و بالتالي هي array من نوع string الآن نحن بحاجة إلى أن نربط كل اسم من هذه الأسماء مع العمر و رقم الهاتف لكل عنصر من العناصر و كأن هذه العناصر ستستبدل بمجموعة تحوي هذه البيانات معا؟ لو فكرنا قليلا.. ما هي الوسيلة المتاحة في swift أو في معظم لغات البرمجة التي تمكنك من ربط عدة بيانات في مجموعة واحدة ؟ الحل ببساطة هو الclass سنقوم بإنشاء كلاس خاص باسم student و سنقوم بوضع الخصائص الخاصة به معا في كلاس واحد : ١- قم بالذهاب إلى file ثم new ثم file ٢- اختر swift file و اضغط على next ٣- قم بتسميته Student و اختر create ملاحظة : من المعتاد دائما البدء بحرف capital لجميع أسماء الكلاسات في المشروع الآن قم بأضافة الكود التالي إلى الملف : //1: class Student { //2: var name:String! var age:Int! var phoneNum:Int! //3: init(name:String,age:Int,phoneNum:Int) { self.name = name self.age = age self.phoneNum = phoneNum } } في الخطوة الأولى قمنا بإنشاء الكلاس Student و في الخطوة الثانية قمنا بإضافة المتغيرات الخاصة بهذا الكلاس و هي الاسم و العمر و رقم الجوال و أخيرا في الخطوة الثالثة قمنا بعمل الinitializer و هي الدالة التي ستستخدم لعمل كائنات أو objects من هذا الكلاس حيث ستستقبل الاسم و العمر و رقم الهاتف لتقوم بعمل أوبجكت جديد يحوي هذه المتغيرات. و الآن قم بالعودة إلى ViewController و قم بتغيير نوع الarray من String إلى Student و قم ببناء العناصر الجديدة لتكون من Students و لتبدو الarray بهذه الطريقة : //1 //var students : [String] = ["محمد","خالد","عمر","أحمد","سامي"] //2 var students : [Student] = [Student(name:"محمد",age:14,phoneNum:054050433), Student(name:"خالد",age:15,phoneNum:054384953), Student(name:"عمر",age:14,phoneNum:054837495), Student(name:"أحمد",age:17,phoneNum:054333874), Student(name:"سامي",age:16,phoneNum:0542030245) ] في الخطوة الأولى قمنا بتحويل الشكل القديم للarray ليكون على شكل comment ( بإمكانك مسحها نهائيا كذلك ) و في الخطوة الثانية قمنا بعمل الarray الجديدة و التي تحوي objects من الStudent class و كل أوبجكت فيها له خصائص الاسم و العمر و رقم الجوال. و الآن نحن بحاجة لقراءة هذه البيانات و وضعها في الtableview. في الشكل السابق للarray كنا فقط بحاجة المتغير الذي يحمل اسم textLabel و الموجود بداخل الcell الخاصة بالtable view حيث نقوم بإسناد قيمة اسم الطالب لهذا المتغير.. لكن المشكلة أن هذا مجرد متغير واحد و نحن بحاجة إلى ٣ متغيرات في كل cell لتحوي الاسم و العمر و رقم الهاتف إذا مالحل ؟ إن الcell أو الخلية التي قمنا باستخدامها هي في الحقيقة الخلية الأساسية في البرنامج و التي لا توفر لك كثير من الخيارات لذا نحن بحاجة إلى عمل cell خاصة بنا و تحوي المتغيرات التي تناسب البرنامج الذي نعمل عليه و سنقوم باستخدامها بدلا من الcell الأساسية. و حتى تقوم بإنشائها : ١- اذهب إلى file ثم new ثم file ٢- هذه المرة سنقوم بعمل cell خاصة بنا لكنها في النهاية ليست إلا cell ترث الخصائص الأساسية من TableViewCell و هو يمثل الكلاس الخاص بالcell الأساسية في الxcode و التي قمنا باستخدامها سابقا ( و بما أننا سنحتاج إلى الوراثة هنا فلن نقوم باختيار swift file و إنشاء كلاس عادي و إنما سنختار cocoa touch class ) ثم اضغط next ٣- في مربع subclass of : قم بتحديد UITableviewCell و قم بتسميتها StudentCell و اختر next ثم create ٤- الآن هذا هو الكلاس الذي سيمثل الcell الجديدة و الذي سيمثل الأكواد التي ستكتب فيها.. لكن أين هي هذه الcell الجديدة في الواجهة ؟ توجه إلى Main storyboard و قم بتحديد الخلية الموجودة في الtableview ملاحطة : إذا لم تكن تظهر لك أي خلية في الtableview فقم بتحديد الtableview و إضافة واحدة من شريط الخصائص كما هو موضح في الصورة التالية : و اجعل هذه الخلية ترث من ال class ( انظر إلى الصورة ) الذي قمنا بعمله للتو و هو StudentCell و ذلك من خلال اختيار شكل المربع ( show the identity inspector ) و من ثم كتابة الاسم في خانة class و بذلك ستمثل هذه الخلية نموذج لشكل كل الخلايا التي سيتم إنشاؤها في الtableview و ما سيجري على شكلها و تصميمها سيجري على كل الخلايا الأخرى في الtableview و لكن حتى تستطيع الوصول إلى هذه الخلية دون غيرها في الكود الخاص بك فأنت بحاجة لإضافة ID خاص بهذه الخلية ليميزها عن غيرها و هذا يتم من خلال تحديد الخلية ثم توجه إلى شريط الخصائص في الجانب الأيمن ستجد خاصية باسم : identifier قم بكتابة الid الذي تجده مناسبا لك مثل : studentCellId على سبيل المثال و لكن تذكره جيدا لأنك ستحتاجه وقت كتابة الكود الخاص بهذه الخلية و الآن قم بتصميم العناصر التي ستحمل بيانات الطلاب و هي تتم بكل بساطة عن طريق إضافة 3 labels للخلية و كل منها سيمثل أحد البيانات ملاحظة : قم بإضافة الأشكال ( labels ) و توزيعها بالطريقة التي تناسبك و لا تنس إضافة الconstraints و إذا أردت إضافتها بسرعة دون الدخول في تفاصيل الconstraints فقم بتحديد العناصر ثم قم بإضافتها كما هو موضح في الصورة : الآن نحن بحاجة لربط الlabels الموجودة في الخلية مع الكلاس الخاص بها حتى تكون لنا قدرة التحكم بها و بقيمها لذلك قم بفتح الكود في نصف الشاشة عن طريق الضغط على أيقونة الدائرتين الموجودة في الزاوية اليمنى من الشريط العلوي تأكد أن الملف المفتوح في النصف الخاص بالكود هو كلاس الStudentCell و إذا لم يكن فتوجه إلى الكلاس من العمود الأيسر الخاص بالملفات و اضغط على alt ثم اسم الكلاس و هو StudentCell توجه الآن إلى أول label و هو الخاص بالاسم و قم بالضغط على ctrl و السحب من الlabel إلى داخل الclass و ستظهر لك نافذة تسأل عن الاسم كما في الصورة قم بتسميته nameLabel و اضغط على connect قم بتكرار نفس العملية للlabel الخاص بالعمر و رقم الهاتف و قم بتسميتهم ageLabel و phoneNumLabel على التوالي. و سيكون الشكل و الكود بهذا الشكل : أخيرا تبقت خطوة أخيرة و هي إضافة القيم المناسبة لكل label في كل خلية و هذا سيتم من خلال الfunction التي تحمل اسم cellForRowAtIndexPath و الموجودة في الكلاس ViewController لذلك توجه إليها و قم بمسح الكود السابق الموجود بداخلها و استبدله بالكود التالي : func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //1 let cell = tableView.dequeueReusableCell(withIdentifier: "studentCellId") as! StudentCell //2 cell.nameLabel.text = students[indexPath.row].name cell.ageLabel.text = String(students[indexPath.row].age) cell.phoneNumLabel.text = String(students[indexPath.row].phoneNum) return cell } في الخطوة الأولى : قمنا باستخدام الtableview و هو المتغير الذي يمثل الtableview الموجود في الstoryboard و الذي يحوي الخلية و الذي قمنا بإضافته في الدرس السابق و قمنا من خلاله باستدعاء function اسمها dequeueReusableCell و التي تستخدم لجلب الcell من خلال الid الخاص بها و لذلك قمنا بإضافة الid الذي قمنا بإنشائه سابقا إلى الخانة الخاصة به كparameter للfunction ثم أضفنا : as! StudentCell حتى نقوم بعمل casting لهذه الcell لتصبح من نوع StudentCell ملاحظة : إذا كنت لا تعلم ما هو الcasting فيمكنك تجاهله الآن و إضافة الكود كما هو و تعلمه لاحقا و الأن أصبح لدينا cell من نوع StudentCell بمعنى آخر : يمكننا الآن الوصول إلى الlabels الموجودة في الStudentCell و تغيير قيمها اعتمادا على قيم العنصر في الarray و هذا ما قمنا بفعله في الخطوة الثانية و هذا الكود شبيه جدا للكود السابق الذي كان خاصا بإضافة الاسم فقط في كل indexPath من الarray باستثناء إضافة الخصائص الخاصة بكل عنصر للarray و ذلك لأن الarray الآن تحتوي على objects و أنت تريد الوصول إلى متغيرات هذا الobjects فتضيف .name للوصول للاسم مثلا و كذلك الأمر للعمر و رقم الهاتف لاحظ كذلك أننا قمنا بتحويل العمر و رقم الهاتف إلى قيم من نوع String و ذلك لأن القيم الأساسية لها هي في الحقيقة من نوع Int و لابد من تحويلها إلى String لتناسب نوعية المتغير text بداخل الLabel الآن قم بتشغيل البرنامج لتظهر لك بهذا الشكل حيث يظهر الخلية و هوي تحوي عدة بيانات متعلقة بالطالب بدلا من الاسم فقط : إلى هنا نصل معكم إلى نهاية الدرس و أتمنى أن يكون ذا فائدة و نفع للقارئ الكريم و إلى اللقاء في دروس أخرى
  6. البرنامج المستخدم : xcode 8 اللغة المستخدمة : swift 3 هذا الدرس هو الجزء الثاني من درس الtableview في الxcode إذا كنت لم تشاهد الجزء الأول فقم بمشاهدته الآن من خلال الرابط التالي : في الدرس السابق وصلنا في النهاية إلى هذه النتيجة.. و هي تمثل جدول أو tableview يحوي أسماء الطلاب، و في هذا الدرس سنقوم بتطوير هذا الجدول و تحسينه ليحوي بيانات أكثر عن كل طالب و بالشكل الذي تختاره أنت كمطور. إذا لنبدأ.. الآن إضافةً لعرض أسماء الطلاب نريد عرض بيانات خاصة بهم كالعمر و رقم الجوال و سنقوم بعرض هذه البيانات في الجدول. و بالتالي فأن كل طالب سيكون له ٣ بيانات مختلفة متصلة به و خاصة به و هي الاسم و العمر و رقم الجوال بدلا من الاسم وحده. و بالتالي كيف يمكن أن نربط مجموعة من البيانات لشيء واحد فقط ؟ لو عدنا إلى الarray التي تمثل مصدر البيانات أو الdata source للtableview و التي تحمل اسم students فسنجد أنها تحتوي على أسماء الطلاب فقط و بالتالي هي array من نوع string الآن نحن بحاجة إلى أن نربط كل اسم من هذه الأسماء مع العمر و رقم الهاتف لكل عنصر من العناصر و كأن هذه العناصر ستستبدل بمجموعة تحوي هذه البيانات معا؟ لو فكرنا قليلا.. ما هي الوسيلة المتاحة في swift أو في معظم لغات البرمجة التي تمكنك من ربط عدة بيانات في مجموعة واحدة ؟ الحل ببساطة هو الclass سنقوم بإنشاء كلاس خاص باسم student و سنقوم بوضع الخصائص الخاصة به معا في كلاس واحد : ١- قم بالذهاب إلى file ثم new ثم file ٢- اختر swift file و اضغط على next ٣- قم بتسميته Student و اختر create ملاحظة : من المعتاد دائما البدء بحرف capital لجميع أسماء الكلاسات في المشروع الآن قم بأضافة الكود التالي إلى الملف : //1: class Student { //2: var name:String! var age:Int! var phoneNum:Int! //3: init(name:String,age:Int,phoneNum:Int) { self.name = name self.age = age self.phoneNum = phoneNum } } في الخطوة الأولى قمنا بإنشاء الكلاس Student و في الخطوة الثانية قمنا بإضافة المتغيرات الخاصة بهذا الكلاس و هي الاسم و العمر و رقم الجوال و أخيرا في الخطوة الثالثة قمنا بعمل الinitializer و هي الدالة التي ستستخدم لعمل كائنات أو objects من هذا الكلاس حيث ستستقبل الاسم و العمر و رقم الهاتف لتقوم بعمل أوبجكت جديد يحوي هذه المتغيرات. و الآن قم بالعودة إلى ViewController و قم بتغيير نوع الarray من String إلى Student و قم ببناء العناصر الجديدة لتكون من Students و لتبدو الarray بهذه الطريقة : //1 //var students : [String] = ["محمد","خالد","عمر","أحمد","سامي"] //2 var students : [Student] = [Student(name:"محمد",age:14,phoneNum:054050433), Student(name:"خالد",age:15,phoneNum:054384953), Student(name:"عمر",age:14,phoneNum:054837495), Student(name:"أحمد",age:17,phoneNum:054333874), Student(name:"سامي",age:16,phoneNum:0542030245) ] في الخطوة الأولى قمنا بتحويل الشكل القديم للarray ليكون على شكل comment ( بإمكانك مسحها نهائيا كذلك ) و في الخطوة الثانية قمنا بعمل الarray الجديدة و التي تحوي objects من الStudent class و كل أوبجكت فيها له خصائص الاسم و العمر و رقم الجوال. و الآن نحن بحاجة لقراءة هذه البيانات و وضعها في الtableview. في الشكل السابق للarray كنا فقط بحاجة المتغير الذي يحمل اسم textLabel و الموجود بداخل الcell الخاصة بالtable view حيث نقوم بإسناد قيمة اسم الطالب لهذا المتغير.. لكن المشكلة أن هذا مجرد متغير واحد و نحن بحاجة إلى ٣ متغيرات في كل cell لتحوي الاسم و العمر و رقم الهاتف إذا مالحل ؟ إن الcell أو الخلية التي قمنا باستخدامها هي في الحقيقة الخلية الأساسية في البرنامج و التي لا توفر لك كثير من الخيارات لذا نحن بحاجة إلى عمل cell خاصة بنا و تحوي المتغيرات التي تناسب البرنامج الذي نعمل عليه و سنقوم باستخدامها بدلا من الcell الأساسية. و حتى تقوم بإنشائها : ١- اذهب إلى file ثم new ثم file ٢- هذه المرة سنقوم بعمل cell خاصة بنا لكنها في النهاية ليست إلا cell ترث الخصائص الأساسية من TableViewCell و هو يمثل الكلاس الخاص بالcell الأساسية في الxcode و التي قمنا باستخدامها سابقا ( و بما أننا سنحتاج إلى الوراثة هنا فلن نقوم باختيار swift file و إنشاء كلاس عادي و إنما سنختار cocoa touch class ) ثم اضغط next ٣- في مربع subclass of : قم بتحديد UITableviewCell و قم بتسميتها StudentCell و اختر next ثم create ٤- الآن هذا هو الكلاس الذي سيمثل الcell الجديدة و الذي سيمثل الأكواد التي ستكتب فيها.. لكن أين هي هذه الcell الجديدة في الواجهة ؟ توجه إلى Main storyboard و قم بتحديد الخلية الموجودة في الtableview ملاحطة : إذا لم تكن تظهر لك أي خلية في الtableview فقم بتحديد الtableview و إضافة واحدة من شريط الخصائص كما هو موضح في الصورة التالية : و اجعل هذه الخلية ترث من ال class ( انظر إلى الصورة ) الذي قمنا بعمله للتو و هو StudentCell و ذلك من خلال اختيار شكل المربع ( show the identity inspector ) و من ثم كتابة الاسم في خانة class و بذلك ستمثل هذه الخلية نموذج لشكل كل الخلايا التي سيتم إنشاؤها في الtableview و ما سيجري على شكلها و تصميمها سيجري على كل الخلايا الأخرى في الtableview و لكن حتى تستطيع الوصول إلى هذه الخلية دون غيرها في الكود الخاص بك فأنت بحاجة لإضافة ID خاص بهذه الخلية ليميزها عن غيرها و هذا يتم من خلال تحديد الخلية ثم توجه إلى شريط الخصائص في الجانب الأيمن ستجد خاصية باسم : identifier قم بكتابة الid الذي تجده مناسبا لك مثل : studentCellId على سبيل المثال و لكن تذكره جيدا لأنك ستحتاجه وقت كتابة الكود الخاص بهذه الخلية و الآن قم بتصميم العناصر التي ستحمل بيانات الطلاب و هي تتم بكل بساطة عن طريق إضافة 3 labels للخلية و كل منها سيمثل أحد البيانات ملاحظة : قم بإضافة الأشكال ( labels ) و توزيعها بالطريقة التي تناسبك و لا تنس إضافة الconstraints و إذا أردت إضافتها بسرعة دون الدخول في تفاصيل الconstraints فقم بتحديد العناصر ثم قم بإضافتها كما هو موضح في الصورة : الآن نحن بحاجة لربط الlabels الموجودة في الخلية مع الكلاس الخاص بها حتى تكون لنا قدرة التحكم بها و بقيمها لذلك قم بفتح الكود في نصف الشاشة عن طريق الضغط على أيقونة الدائرتين الموجودة في الزاوية اليمنى من الشريط العلوي تأكد أن الملف المفتوح في النصف الخاص بالكود هو كلاس الStudentCell و إذا لم يكن فتوجه إلى الكلاس من العمود الأيسر الخاص بالملفات و اضغط على alt ثم اسم الكلاس و هو StudentCell توجه الآن إلى أول label و هو الخاص بالاسم و قم بالضغط على ctrl و السحب من الlabel إلى داخل الclass و ستظهر لك نافذة تسأل عن الاسم كما في الصورة قم بتسميته nameLabel و اضغط على connect قم بتكرار نفس العملية للlabel الخاص بالعمر و رقم الهاتف و قم بتسميتهم ageLabel و phoneNumLabel على التوالي. و سيكون الشكل و الكود بهذا الشكل : أخيرا تبقت خطوة أخيرة و هي إضافة القيم المناسبة لكل label في كل خلية و هذا سيتم من خلال الfunction التي تحمل اسم cellForRowAtIndexPath و الموجودة في الكلاس ViewController لذلك توجه إليها و قم بمسح الكود السابق الموجود بداخلها و استبدله بالكود التالي : func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //1 let cell = tableView.dequeueReusableCell(withIdentifier: "studentCellId") as! StudentCell //2 cell.nameLabel.text = students[indexPath.row].name cell.ageLabel.text = String(students[indexPath.row].age) cell.phoneNumLabel.text = String(students[indexPath.row].phoneNum) return cell } في الخطوة الأولى : قمنا باستخدام الtableview و هو المتغير الذي يمثل الtableview الموجود في الstoryboard و الذي يحوي الخلية و الذي قمنا بإضافته في الدرس السابق و قمنا من خلاله باستدعاء function اسمها dequeueReusableCell و التي تستخدم لجلب الcell من خلال الid الخاص بها و لذلك قمنا بإضافة الid الذي قمنا بإنشائه سابقا إلى الخانة الخاصة به كparameter للfunction ثم أضفنا : as! StudentCell حتى نقوم بعمل casting لهذه الcell لتصبح من نوع StudentCell ملاحظة : إذا كنت لا تعلم ما هو الcasting فيمكنك تجاهله الآن و إضافة الكود كما هو و تعلمه لاحقا و الأن أصبح لدينا cell من نوع StudentCell بمعنى آخر : يمكننا الآن الوصول إلى الlabels الموجودة في الStudentCell و تغيير قيمها اعتمادا على قيم العنصر في الarray و هذا ما قمنا بفعله في الخطوة الثانية و هذا الكود شبيه جدا للكود السابق الذي كان خاصا بإضافة الاسم فقط في كل indexPath من الarray باستثناء إضافة الخصائص الخاصة بكل عنصر للarray و ذلك لأن الarray الآن تحتوي على objects و أنت تريد الوصول إلى متغيرات هذا الobjects فتضيف .name للوصول للاسم مثلا و كذلك الأمر للعمر و رقم الهاتف لاحظ كذلك أننا قمنا بتحويل العمر و رقم الهاتف إلى قيم من نوع String و ذلك لأن القيم الأساسية لها هي في الحقيقة من نوع Int و لابد من تحويلها إلى String لتناسب نوعية المتغير text بداخل الLabel الآن قم بتشغيل البرنامج لتظهر لك بهذا الشكل حيث يظهر الخلية و هوي تحوي عدة بيانات متعلقة بالطالب بدلا من الاسم فقط : إلى هنا نصل معكم إلى نهاية الدرس و أتمنى أن يكون ذا فائدة و نفع للقارئ الكريم و إلى اللقاء في دروس أخرى تم ترقية هذا الطرح المميز الى صفحة المقالات
  7. في هذا الدرس سنتعلم كيفية التعامل مع الtableview مع الـ Swift و كيفية إنشائه و بنائه داخل تطبيقك. في البداية ما هو الtableview ؟ الtableview هو أداة من أدوات واجهة المستخدم التي تستخدم لعرض البيانات من خلالها. و تحديدا تستخدم في عرض البيانات التي تكون على شكل مجموعة عناصر مثل قائمة بمحتويات مطعم أو أسماء لطلاب في مدرسة..الخ و الحقيقة أنه لا يكاد يتواجد تطبيق في متجر البرامج دون وجود tableview بما في ذلك التطبيقات الشهيرة كتطبيق facebook فكل البوستات الموجودة في الfacebook و التي تشاهدها في الصفحة الرئيسية عند فتح التطبيق ما هي إلا شرائح من هذا الtableview و كذلك في twitter و instegram... الخ. و لذلك يعتبر الtableview أحد أهم الأدوات الموجودة في برنامج الxcode و من أكثر الأدوات استخداما في بناء التطبيقات إن لم يكن أكثرها لذلك من المهم لمبرمج التطبيقات أن يتعلم طريقة إنشائه و التعامل معه في التطبيق و ما سنقوم بعمله في هذا الدرس هو عرض قائمة لأسماء طلاب في الtableview و لذلك فلنبدأ... في البداية قم بفتح الإكسكود و قم بعمل باختيار create new xcode project ثم single view application و قم بتسميته و حفظه. الآن قم بالتوجه إلى الMain.storyboard لإضافة الtableview إلى تطبيقك. لإدراج الtableview توجه إلى مكتبة العناصر الموجودة على اليسار و قم بالبحث عن tableview كما ثم اسحبه إلى الشاشة كما هو موضح في الصور. ملاحظة: تأكد من سحبك لعنصر الtableview و ليس لعنصر الtableview controller الآن قم بتعديل حجم الtableview ليملأ الشاشة بأكملها قم بإضافة الconstraints كما هو موضح في الصورة إذا كنت لا تعلم ما هي الconstraints فيمكنك تجاهلها الآن، و لكنها باختصار طريقة لإظهار الui أو عناصر واجهة المستخدم كالtableview بشكل مناسب في جميع الشاشات المختلفة الحجم. الآن تم إضافة الtableview إلي التطبيق يمكنك عمل run و تشغيل التطبيق الآن، ستلاحظ وجود جدول محتويات بخلايا فارغة و الآن سنقوم بإكمال العملية لملء هذه الخانات ببيانات معينة: إن الview controller الموجودة في الstoryboard و التي قمنا بإضافة الtableview إليها تمتلك ملف برمجي متصل بها يمكنك من كتابة الأكواد الخاصة بهذا الview controller بداخله و حتى تعرف ما هو هذا الملف البرمجي قم بالضغط على الدائرة الصفراء في زاوية الشريط العلوي للview controller ثم قم باختيار المربع من الشريط الأيمن في البرنامج ثم لاحظ خانة الcustom claass ستجد أن الclass أو ملف الكود المرتبط بهذا الview controller هو ملف ViewController و الذي تم إنشاؤه تلقائيا، لاحظ الصورة: الآن من الشريط العلوي تماما في البرنامج قم باختيار رمز الدائرتين لعرض ملف الكود ViewController بجانب الmain story board الآن قم بالضغط على زر ctrl و قم بالسحب من الtableview الذي قمت بإضافته إلى داخل الكلاس على الجانب الآخر و قم بتسميته studentsTebleview أو namesTableview الآن أصبح لدينا متغير بداخل الviewController باسم studentsTableview ليمثل الtableview على شكل كود. حتى نملأ هذا الtableview بالمحتويات فإننا نحتاج أن نخبر البرنامج أن مصدر هذه المحتويات سيكون هذا الViewController الذي قمنا بإضافة الstudentsTableview إليه، لكن كيف يتم ذلك ؟ اذهب إلى الfunction التي تحمل اسم viewDidLoad و التي يتم استدعاؤها تلقائيا و يتم تنفيذ الكود الذي بداخلها تلقائيا بمجرد تشغيل البرنامج و اكتب بداخلها : override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. studentsTableview.dataSource = self } و بهذا تكون قد عرّفت أن مصدر البيانات سيكون هذا الاوبجكت من الكلاس ViewController لكن ستلاحظ ظهور خطأ و هذا الخطأ يظهر بسبب أن نوع المتغير الذي يجب أن يكون مصدرا لبيانات الtableview يجب أن يكون من نوع UITableViewDataSource بينما نلاحظ أن الكلاس ViewController يرث من الكلاس UIViewController و ليس من UITableViewDataSource لذلك لابد أن يرث كذلك من UITableViewDataSource و بالتالي قم بإضافة هذا إلى الكلاس ViewController ليظهر كما هو موضح في الصورة : كما تلاحظ ما زال هناك خطأ و هذا الخطأ بسبب عدم كتابة الfunctions التي تتطلبها الوراثة من UITableViewDataSource و عدد الfunctions التي يجب كتابتها هو ٣ دوال رئيسية و هم : - numberOfSections : و هي التي ستقوم فيها بإرجاع عدد المجموعات لتحوي التصنيفات المختلفة ( و غالبا ما تستخدم مجموعة واحدة فقط ) - numberOfRowsInSection : و هي التي تستخدم لتحديد عدد الصفوف أو الخلايا في كل مجموعة - cellForRowAtIndexPath : و هي التي تستخدم لتحديد بيانات كل خلية في الtableview و لكتابة هذه الfunctions قم بكتابة العناوين الموضحة في الأعلى و سيقوم الإكمال التلقائي في البرنامج باقتراح خيارات لـإكمالها ثم اضغط على enter حالما تجد الfunction الصحيحة التي تريدها.. سيكون شكل الكود بعد كتابة الfunctions كالتالي : في الfunction الأولى قم بكتابة return 1 لتقوم بعمل مجموعة واحدة للخلايا في الfunction الثانية قم بكتابة return 7 كعدد مبدئي لإعادة ٧ صفوف في الtableview و في الfunction الثالثة كما هو موضح من الfunction أن هذه الfunction يجب أن تقوم بإرجاع قيمة من UITAbleviewCell و هي الشريحة التي سيتم عرضها في الtableview لذلك مبدئيا قم بكتابة : let cell = UITableViewCell() cell.textLabel?.text = "hello" return cell و ما قمنا بفعله هنا هو إنشاء cell من نوع UITableviewCell و قمنا بجعل الtext الخاص بها ليحوي كلمة hello و هذا سيطبق على كل الخلايا السبعة في الtableview و بالتالي سيكون شكل الكود كالتالي : الآن قم بتشغيل البرنامج لاختبار الكود سيظهر لك ٧ خلايا في جدول محتويات و كلها تحتوي على كلمة hello كما يبدو في الصورة.. أخيرا! قمنا بعمل tableview يقوم بعرض محتويات قمنا بتحديدها على الcell و لكن تبقى المشكلة في أن هذه المحتويات كلها متشابهة و لا تحوي مجموعة لأسماء الطلاب كما نريد فكيف نقوم بذلك ؟ عادة عند التعامل مع الtableview لابد أن يكون هناك مصدر للبيانات لأخذ البيانات منه و عادة ما يكون هذا المصدر على شكل array لذلك قم بعمل array من نوع [String] لتحوي أسماء الطلاب و قم بوضع الأسماء كما في الصورة أو كما تريد : الآن قم بالتوجه إلى الfunction التي تحمل الاسم numberOfRowsInSection و قم بإعادة عدد عناصر الarray بدلا من عدد ٧ العشوائي. return students.count الآن توجه إلى الfunction التي تحمل اسم cellForRowAtIndexPath و لاحظ أن هذه الfunction تحتوي على بارامتر باسم indexPath. في الحقيقة.. هذه الfunction يتم استدعؤها عدة مرات و ليس مرة واحدة و عدد المرات التي يتم استدعاؤها فيه يساوي عدد الصفوف التي قمت بإرجاعها في الfunction ذات اسم numberOfRowsInSection و بالتالي عدد مرات استدعائها سيكون مساويا لعدد عناصر الstudents array في هذه الحالة حيث يقوم البرنامج بكل مرة بإعادة خلية لتمثل البيانات التي سيتم عرضها في ذلك الصف. المهم في الأمر أن البارامتر indexPath يحتوي على خاصية باسم row من نوع Int. و هذه الخاصية لاتحمل قيمة ثابتة في كل استدعاء للcellForRowAtIndex function و أنما تبدأ بقيمة 0 و في الاستدعاء التالي تزيد بمقدار ١ فتصبح قيمتها ١ ثم تنتقل إلى الاستدعاء التالي لتصبح قيمتها ٢ ثم ٣ ثم ٤... الخ حتى تنتهي عند آخر رقم و الذي يساوي حسب ما فهمنا في الأعلى عدد عناصر الstudents array ناقص واحد ( لأن العد سيبدأ من 0 )... لعلك بدأت تفهم الفكرة.. يمكننا أن نعتمد على هذا المتغير لأخذ البيانات من الarray بالترتيب و إسنادها إلى الخلايا... لذلك بداخل الcellForRowAtIndex function قم بتعديل الكود ليكون كالتالي.. let cell = UITableViewCell() cell.textLabel?.text = students[indexPath.row] return cell و شكل الكود كاملا سيبدو كالتالي... الآن قم بتشغيل البرنامج و انظر إلى النتيجة النهائية إلى هنا نصل إلى نهاية الدرس و سنتناول الموضوع بطريقة متقدمة مستقبلا إن شاء الله.
  8. في هذا الدرس سنتعلم كيفية التعامل مع الtableview في الxcode و كيفية إنشائه و بنائه داخل تطبيقك. في البداية ما هو الtableview ؟ الtableview هو أداة من أدوات واجهة المستخدم التي تستخدم لعرض البيانات من خلالها. و تحديدا تستخدم في عرض البيانات التي تكون على شكل مجموعة عناصر مثل قائمة بمحتويات مطعم أو أسماء لطلاب في مدرسة..الخ و الحقيقة أنه لا يكاد يتواجد تطبيق في متجر البرامج دون وجود tableview بما في ذلك التطبيقات الشهيرة كتطبيق facebook فكل البوستات الموجودة في الfacebook و التي تشاهدها في الصفحة الرئيسية عند فتح التطبيق ما هي إلا شرائح من هذا الtableview و كذلك في twitter و instegram... الخ. و لذلك يعتبر الtableview أحد أهم الأدوات الموجودة في برنامج الxcode و من أكثر الأدوات استخداما في بناء التطبيقات إن لم يكن أكثرها لذلك من المهم لمبرمج التطبيقات أن يتعلم طريقة إنشائه و التعامل معه في التطبيق و ما سنقوم بعمله في هذا الدرس هو عرض قائمة لأسماء طلاب في الtableview و لذلك فلنبدأ... في البداية قم بفتح الإكسكود و قم بعمل باختيار create new xcode project ثم single view application و قم بتسميته و حفظه. الآن قم بالتوجه إلى الMain.storyboard لإضافة الtableview إلى تطبيقك. لإدراج الtableview توجه إلى مكتبة العناصر الموجودة على اليسار و قم بالبحث عن tableview كما ثم اسحبه إلى الشاشة كما هو موضح في الصور. ملاحظة: تأكد من سحبك لعنصر الtableview و ليس لعنصر الtableview controller الآن قم بتعديل حجم الtableview ليملأ الشاشة بأكملها قم بإضافة الconstraints كما هو موضح في الصورة إذا كنت لا تعلم ما هي الconstraints فيمكنك تجاهلها الآن، و لكنها باختصار طريقة لإظهار الui أو عناصر واجهة المستخدم كالtableview بشكل مناسب في جميع الشاشات المختلفة الحجم. الآن تم إضافة الtableview إلي التطبيق يمكنك عمل run و تشغيل التطبيق الآن، ستلاحظ وجود جدول محتويات بخلايا فارغة و الآن سنقوم بإكمال العملية لملء هذه الخانات ببيانات معينة: إن الview controller الموجودة في الstoryboard و التي قمنا بإضافة الtableview إليها تمتلك ملف برمجي متصل بها يمكنك من كتابة الأكواد الخاصة بهذا الview controller بداخله و حتى تعرف ما هو هذا الملف البرمجي قم بالضغط على الدائرة الصفراء في زاوية الشريط العلوي للview controller ثم قم باختيار المربع من الشريط الأيمن في البرنامج ثم لاحظ خانة الcustom claass ستجد أن الclass أو ملف الكود المرتبط بهذا الview controller هو ملف ViewController و الذي تم إنشاؤه تلقائيا، لاحظ الصورة: الآن من الشريط العلوي تماما في البرنامج قم باختيار رمز الدائرتين لعرض ملف الكود ViewController بجانب الmain story board الآن قم بالضغط على زر ctrl و قم بالسحب من الtableview الذي قمت بإضافته إلى داخل الكلاس على الجانب الآخر و قم بتسميته studentsTebleview أو namesTableview الآن أصبح لدينا متغير بداخل الviewController باسم studentsTableview ليمثل الtableview على شكل كود. حتى نملأ هذا الtableview بالمحتويات فإننا نحتاج أن نخبر البرنامج أن مصدر هذه المحتويات سيكون هذا الViewController الذي قمنا بإضافة الstudentsTableview إليه، لكن كيف يتم ذلك ؟ اذهب إلى الfunction التي تحمل اسم viewDidLoad و التي يتم استدعاؤها تلقائيا و يتم تنفيذ الكود الذي بداخلها تلقائيا بمجرد تشغيل البرنامج و اكتب بداخلها : override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. studentsTableview.dataSource = self } و بهذا تكون قد عرّفت أن مصدر البيانات سيكون هذا الاوبجكت من الكلاس ViewController لكن ستلاحظ ظهور خطأ و هذا الخطأ يظهر بسبب أن نوع المتغير الذي يجب أن يكون مصدرا لبيانات الtableview يجب أن يكون من نوع UITableViewDataSource بينما نلاحظ أن الكلاس ViewController يرث من الكلاس UIViewController و ليس من UITableViewDataSource لذلك لابد أن يرث كذلك من UITableViewDataSource و بالتالي قم بإضافة هذا إلى الكلاس ViewController ليظهر كما هو موضح في الصورة : كما تلاحظ ما زال هناك خطأ و هذا الخطأ بسبب عدم كتابة الfunctions التي تتطلبها الوراثة من UITableViewDataSource و عدد الfunctions التي يجب كتابتها هو ٣ دوال رئيسية و هم : - numberOfSections : و هي التي ستقوم فيها بإرجاع عدد المجموعات لتحوي التصنيفات المختلفة ( و غالبا ما تستخدم مجموعة واحدة فقط ) - numberOfRowsInSection : و هي التي تستخدم لتحديد عدد الصفوف أو الخلايا في كل مجموعة - cellForRowAtIndexPath : و هي التي تستخدم لتحديد بيانات كل خلية في الtableview و لكتابة هذه الfunctions قم بكتابة العناوين الموضحة في الأعلى و سيقوم الإكمال التلقائي في البرنامج باقتراح خيارات لـإكمالها ثم اضغط على enter حالما تجد الfunction الصحيحة التي تريدها.. سيكون شكل الكود بعد كتابة الfunctions كالتالي : في الfunction الأولى قم بكتابة return 1 لتقوم بعمل مجموعة واحدة للخلايا في الfunction الثانية قم بكتابة return 7 كعدد مبدئي لإعادة ٧ صفوف في الtableview و في الfunction الثالثة كما هو موضح من الfunction أن هذه الfunction يجب أن تقوم بإرجاع قيمة من UITAbleviewCell و هي الشريحة التي سيتم عرضها في الtableview لذلك مبدئيا قم بكتابة : let cell = UITableViewCell() cell.textLabel?.text = "hello" return cell و ما قمنا بفعله هنا هو إنشاء cell من نوع UITableviewCell و قمنا بجعل الtext الخاص بها ليحوي كلمة hello و هذا سيطبق على كل الخلايا السبعة في الtableview و بالتالي سيكون شكل الكود كالتالي : الآن قم بتشغيل البرنامج لاختبار الكود سيظهر لك ٧ خلايا في جدول محتويات و كلها تحتوي على كلمة hello كما يبدو في الصورة.. أخيرا! قمنا بعمل tableview يقوم بعرض محتويات قمنا بتحديدها على الcell و لكن تبقى المشكلة في أن هذه المحتويات كلها متشابهة و لا تحوي مجموعة لأسماء الطلاب كما نريد فكيف نقوم بذلك ؟ عادة عند التعامل مع الtableview لابد أن يكون هناك مصدر للبيانات لأخذ البيانات منه و عادة ما يكون هذا المصدر على شكل array لذلك قم بعمل array من نوع [String] لتحوي أسماء الطلاب و قم بوضع الأسماء كما في الصورة أو كما تريد : الآن قم بالتوجه إلى الfunction التي تحمل الاسم numberOfRowsInSection و قم بإعادة عدد عناصر الarray بدلا من عدد ٧ العشوائي. return students.count الآن توجه إلى الfunction التي تحمل اسم cellForRowAtIndexPath و لاحظ أن هذه الfunction تحتوي على بارامتر باسم indexPath. في الحقيقة.. هذه الfunction يتم استدعؤها عدة مرات و ليس مرة واحدة و عدد المرات التي يتم استدعاؤها فيه يساوي عدد الصفوف التي قمت بإرجاعها في الfunction ذات اسم numberOfRowsInSection و بالتالي عدد مرات استدعائها سيكون مساويا لعدد عناصر الstudents array في هذه الحالة حيث يقوم البرنامج بكل مرة بإعادة خلية لتمثل البيانات التي سيتم عرضها في ذلك الصف. المهم في الأمر أن البارامتر indexPath يحتوي على خاصية باسم row من نوع Int. و هذه الخاصية لاتحمل قيمة ثابتة في كل استدعاء للcellForRowAtIndex function و أنما تبدأ بقيمة 0 و في الاستدعاء التالي تزيد بمقدار ١ فتصبح قيمتها ١ ثم تنتقل إلى الاستدعاء التالي لتصبح قيمتها ٢ ثم ٣ ثم ٤... الخ حتى تنتهي عند آخر رقم و الذي يساوي حسب ما فهمنا في الأعلى عدد عناصر الstudents array ناقص واحد ( لأن العد سيبدأ من 0 )... لعلك بدأت تفهم الفكرة.. يمكننا أن نعتمد على هذا المتغير لأخذ البيانات من الarray بالترتيب و إسنادها إلى الخلايا... لذلك بداخل الcellForRowAtIndex function قم بتعديل الكود ليكون كالتالي.. let cell = UITableViewCell() cell.textLabel?.text = students[indexPath.row] return cell و شكل الكود كاملا سيبدو كالتالي... الآن قم بتشغيل البرنامج و انظر إلى النتيجة النهائية إلى هنا نصل إلى نهاية الدرس و سنتناول الموضوع بطريقة متقدمة مستقبلا إن شاء الله. تم ترقية هذا الطرح المميز الى صفحة المقالات
  9. اللغة المستخدمة : swift 3 البرنامج المستخدم : xcode 8 في هذا الدرس سوف نتعلم طريقة تطبيق الsingleton design pattern في برنامج الxcode و في لغة برمجة swift لكن في البداية لمأخذ مقدمة بسيطة عن الdesign pattern ، إذا ما هو الdesign pattern ؟ الdesign pattern هي طريقة معينة أو نمط معين يستخدمه المبرمج لكتابة الكود البرمجي. لكن لماذا يستخدم هذه الطرق عوضا عن أي طريقة أخرى؟ -في البرمجة وارد جدا أن تتعرض للمشكلات و أنا لا أتحدث هنا عن مشكلات الoutput فقط و إنما قد تواجه مشاكل معينة متعلقة بالطريقة التي قمت ببناء الكود عليها و هذه المشكلات غالبا ما تتواجد فيها خاصيتين رئيسيتين : أن هذه المشكلات تحدث مع المبرمجين بشكل متكرر . غالبا عند التعرض لأحد هذه المشكلات فإن إصلاحها سيكون مكلفا بمعنى أن المبرمج سيحتاج إلى إعادة كتابة كمية ليست بالقليلة من الأكواد لإصلاح المشكلة و الوصول إلى حل. و لذلك يتم اسخدام طرق معينة لبناء الكود البرمجي تسمى design patterns. لنفرض أنك تعمل على تطبيق آيفون خاص بإدارة حسابات بنكية و لديك class باسم bankManager حيث يستخدم هذا الكلاس لإدارة كل العمليات المتعلقة بالبنك فعلى سبيل المثال يوجد به function خاصة بإيداع الأموال في حساب ما.. التي تتلقى باراميتر للid الخاص بالحساب و تتلقى بارامتر آخر لكمية المبلغ الذي سيتم إيداعه كذلك يحوي هذا الحساب function لسحب المبلغ و أخرى لتحويل المبلغ لحساب آخر.. الخ و بالتالي فإن هذا الclass سيحوي كل هذه الأوامر المهة التي ستستخدم في التطبيق. و هذه الأوامر سستستخدمها في كل الclasses التي ستقوم بإنشائها في تطبيقك بمعنى آخر.. ستحتاج لأن يكون لديك object من الكلاس bankManager في كل الclasses لديك في التطبيق لأنك ستحتاج حتما لاستخدام الأوامر المهمة في يحويها هذا الclass في أغلب الclasses في تطبيقك. لكن هل إنشاء object من الbankManager في كل الكلاسات التي لديك هي طريقة جيدة للعمل مع هذا الكلاس ؟ بمعنى آخر هل من المناسب إنشاء عدد من الobjects من كلاس الbankManager أم يجب أن يكون لدينا فقط object واحد مشترك بين كل الكلاسات ؟ الحقيقة أن إنشاء object واحد فقط مشترك بين كل الكلاسات هي الطريقة المثلى للتعامل مع ال objects من هذا الكلاس و لذلك فإنك بطريقة ما تحتاج لأن تجبر الكلاس على إنشاء object واحد فقط و إرجاع نفس الobject في كل مرة يتم فيها محاولة عمل object جديد من هذا الكلاس. لكن كيف يتم ذلك ؟ ذلك يتم من خلال ما يعرف بالsingleton object أو الsingleton design pattern إذا لنبدأ تطبيق ذلك عمليا : -في البداية افتح الxcode قم بإنشاء مشروع جديد (create new xcode project > single view application ) و قم بتسميته Singleton. - الآن قم بعمل كلاس جديد و قم بتسميته bankManager. - في البداية و كما تعلم نحن بحاجة إلى استخدام object مشترك بين كل الكلاسات و لعل كلمة مشترك ستقودك الى التفكير ب static variable، بالفعل سنحتاج إلى عمل static variable لذلك توجه إلى الbankManager و قم بإضافة object من نوع الكلاس نفسه و هو الbankManager و قم بجعله static و لأن هذا الobject سيبدأ بقيمة nil ثم سيكون ذا قيمة من نوعBankManager عندما يتم استدعاؤه لذلك يجب أن يكون هذا الobject من نوع optional لذلك لا تنس إضافة ( ؟ ) في نهاية تعريفه. - الآن أصبح لدينا أوبجكت مشترك أو يمكن أن يكون مشتركا بين كل الكلاسات لأنه من نوع static. هل هذا يكفي ؟ بالطبع لا. من الذي سيحدد فيما إذا كان الobject قد تم إنشاؤه و بالتالي إعادته نفسه أو إنشاء object جديد في حال أن قيمة الobject في الحقيقة تساوي nil لذا هل يمكنك التفكير بالخطوة القادمة ؟ - الحل هو عمل function تقوم بالمطلوب حيث ستقوم هذه الfunction بالتأكد أن الobject قد تم إنشاؤه و في حال كان الobject قد تم إنشاؤه بالفعل فإنها ستعيد هذا الobject bankManager الذي قمنا بإنشائه في الأعلى و إلا فإنها ستقوم بإنشائه إولا ثم إرجاعه بعد إنشائه. ولأن هذه الfunction سوف تقوم باستخدام object من نوع static إذا هي بحاجة أن تكون static كذلك و بالتالي ستكون الfunction كالتالي : -ملاحظة: من الشائع في برمجة - بعض الأحيان - الآيفون تسمية هذه الfunction اسم مشابه لsharedObject أو sharedManager - قد يرد إلى ذهنك الآن أننا سنستخدم هذه الfunction دائما إذا ما أردنا الوصول إلى الobject مما يعني أننا لن نصل إلى الobject مباشرة عن طريق استدعائه بشكل مباشر باستخدام BankManager.bankManager و الحقيقة أن استدعاءه بهذه الطريقة قد يسبب بعض المشاكل، مثلا: قد تقوم باستدعائه في أحد الكلاسات بهذه الطريقة و قيمته في ذلك التوقيت تساوي nil و فور محاولتك استخدام اي متغير أو function بداخل الكلاس BankManager فأن البرنامج سيتوقف لمحاولتك استدعاء function لعنصر قيمته في الحقيقة تساوي nil و لحل هذه المشكلة و حتى تقطع أي مجال لاستدعاء الobject بهذه الطريقة المباشرة قم بعمل الstatic object ليكون private و بالتالي سيظهر الكود بهذه الطريقة - هل انتهى الأمر تماما؟ في الحقيقة ليس بعد. ماذا إن قمت خطأً بعمل object من كلاس الBankManager بالطريقة العادية لأنشاء Object من الكلاسات في سويفت ؟ أو افرض أنك تعمل في فريق من المبرمجين و قام مبرمج آخر باستكمال العمل من بعدك حينها ستحتاج إلى منعه من عمل object بالطريقة العادية حتى لا تسبب مشاكل أثناء العمل؟ لكن كيف يتم ذلك ؟ كل ما عليك فعله هو أن تجعل الfunction التي تثوم بعمل الobject بطريقة عادية لتكون من نوع private و بالتالي لن يكون بالإمكان استدعاءها خارج الكلاس و سيكون المبرمج مجبرا على استخدام الfunction المسماة sharedObject و الآن هل انتهى الأمر ؟ نعم انتهى الأمر هنا و أصبح الsingleton object جاهزا للاستخدام أخيرا. بقي الإشارة إلى نقطة مهمة، إن كنت من مبرمجيswift المتمرسين، فلعلك لاحظت أن بعض الclasses التي تقوم باستخدامها هي في الحقيقة تطبق الsingleton pattern و من هذه الكلاسات : NSUserDefaults ----> var userDefaults = NSUserDefaults.standardUserDefaults() UIScreen ----> var mainSecreen = UIScreen.mainScreen UIApplication ----> var application = UIApplication.sharedApplication -- لاحظ أن الوصول للshared object يمكن أن يكون عن طريق static method كما شرحنا في هذا الدرس و قد يكون عن طريق static variable ختاما.. أتمنى أن أكون وفقت في الشرح و إيصال الفكرة و أسأل الله أن يجعله من العلم الذي يُنتفع به .
  10. اللغة المستخدمة : swift 3 البرنامج المستخدم : xcode 8 في هذا الدرس سوف نتعلم طريقة تطبيق الsingleton design pattern في برنامج الxcode و في لغة برمجة swift لكن في البداية لمأخذ مقدمة بسيطة عن الdesign pattern ، إذا ما هو الdesign pattern ؟ الdesign pattern هي طريقة معينة أو نمط معين يستخدمه المبرمج لكتابة الكود البرمجي. لكن لماذا يستخدم هذه الطرق عوضا عن أي طريقة أخرى؟ -في البرمجة وارد جدا أن تتعرض للمشكلات و أنا لا أتحدث هنا عن مشكلات الoutput فقط و إنما قد تواجه مشاكل معينة متعلقة بالطريقة التي قمت ببناء الكود عليها و هذه المشكلات غالبا ما تتواجد فيها خاصيتين رئيسيتين : أن هذه المشكلات تحدث مع المبرمجين بشكل متكرر . غالبا عند التعرض لأحد هذه المشكلات فإن إصلاحها سيكون مكلفا بمعنى أن المبرمج سيحتاج إلى إعادة كتابة كمية ليست بالقليلة من الأكواد لإصلاح المشكلة و الوصول إلى حل. و لذلك يتم اسخدام طرق معينة لبناء الكود البرمجي تسمى design patterns. لنفرض أنك تعمل على تطبيق آيفون خاص بإدارة حسابات بنكية و لديك class باسم bankManager حيث يستخدم هذا الكلاس لإدارة كل العمليات المتعلقة بالبنك فعلى سبيل المثال يوجد به function خاصة بإيداع الأموال في حساب ما.. التي تتلقى باراميتر للid الخاص بالحساب و تتلقى بارامتر آخر لكمية المبلغ الذي سيتم إيداعه كذلك يحوي هذا الحساب function لسحب المبلغ و أخرى لتحويل المبلغ لحساب آخر.. الخ و بالتالي فإن هذا الclass سيحوي كل هذه الأوامر المهة التي ستستخدم في التطبيق. و هذه الأوامر سستستخدمها في كل الclasses التي ستقوم بإنشائها في تطبيقك بمعنى آخر.. ستحتاج لأن يكون لديك object من الكلاس bankManager في كل الclasses لديك في التطبيق لأنك ستحتاج حتما لاستخدام الأوامر المهمة في يحويها هذا الclass في أغلب الclasses في تطبيقك. لكن هل إنشاء object من الbankManager في كل الكلاسات التي لديك هي طريقة جيدة للعمل مع هذا الكلاس ؟ بمعنى آخر هل من المناسب إنشاء عدد من الobjects من كلاس الbankManager أم يجب أن يكون لدينا فقط object واحد مشترك بين كل الكلاسات ؟ الحقيقة أن إنشاء object واحد فقط مشترك بين كل الكلاسات هي الطريقة المثلى للتعامل مع ال objects من هذا الكلاس و لذلك فإنك بطريقة ما تحتاج لأن تجبر الكلاس على إنشاء object واحد فقط و إرجاع نفس الobject في كل مرة يتم فيها محاولة عمل object جديد من هذا الكلاس. لكن كيف يتم ذلك ؟ ذلك يتم من خلال ما يعرف بالsingleton object أو الsingleton design pattern إذا لنبدأ تطبيق ذلك عمليا : -في البداية افتح الxcode قم بإنشاء مشروع جديد (create new xcode project > single view application ) و قم بتسميته Singleton. - الآن قم بعمل كلاس جديد و قم بتسميته bankManager. - في البداية و كما تعلم نحن بحاجة إلى استخدام object مشترك بين كل الكلاسات و لعل كلمة مشترك ستقودك الى التفكير ب static variable، بالفعل سنحتاج إلى عمل static variable لذلك توجه إلى الbankManager و قم بإضافة object من نوع الكلاس نفسه و هو الbankManager و قم بجعله static و لأن هذا الobject سيبدأ بقيمة nil ثم سيكون ذا قيمة من نوعBankManager عندما يتم استدعاؤه لذلك يجب أن يكون هذا الobject من نوع optional لذلك لا تنس إضافة ( ؟ ) في نهاية تعريفه. - الآن أصبح لدينا أوبجكت مشترك أو يمكن أن يكون مشتركا بين كل الكلاسات لأنه من نوع static. هل هذا يكفي ؟ بالطبع لا. من الذي سيحدد فيما إذا كان الobject قد تم إنشاؤه و بالتالي إعادته نفسه أو إنشاء object جديد في حال أن قيمة الobject في الحقيقة تساوي nil لذا هل يمكنك التفكير بالخطوة القادمة ؟ - الحل هو عمل function تقوم بالمطلوب حيث ستقوم هذه الfunction بالتأكد أن الobject قد تم إنشاؤه و في حال كان الobject قد تم إنشاؤه بالفعل فإنها ستعيد هذا الobject bankManager الذي قمنا بإنشائه في الأعلى و إلا فإنها ستقوم بإنشائه إولا ثم إرجاعه بعد إنشائه. ولأن هذه الfunction سوف تقوم باستخدام object من نوع static إذا هي بحاجة أن تكون static كذلك و بالتالي ستكون الfunction كالتالي : -ملاحظة: من الشائع في برمجة - بعض الأحيان - الآيفون تسمية هذه الfunction اسم مشابه لsharedObject أو sharedManager - قد يرد إلى ذهنك الآن أننا سنستخدم هذه الfunction دائما إذا ما أردنا الوصول إلى الobject مما يعني أننا لن نصل إلى الobject مباشرة عن طريق استدعائه بشكل مباشر باستخدام BankManager.bankManager و الحقيقة أن استدعاءه بهذه الطريقة قد يسبب بعض المشاكل، مثلا: قد تقوم باستدعائه في أحد الكلاسات بهذه الطريقة و قيمته في ذلك التوقيت تساوي nil و فور محاولتك استخدام اي متغير أو function بداخل الكلاس BankManager فأن البرنامج سيتوقف لمحاولتك استدعاء function لعنصر قيمته في الحقيقة تساوي nil و لحل هذه المشكلة و حتى تقطع أي مجال لاستدعاء الobject بهذه الطريقة المباشرة قم بعمل الstatic object ليكون private و بالتالي سيظهر الكود بهذه الطريقة - هل انتهى الأمر تماما؟ في الحقيقة ليس بعد. ماذا إن قمت خطأً بعمل object من كلاس الBankManager بالطريقة العادية لأنشاء Object من الكلاسات في سويفت ؟ أو افرض أنك تعمل في فريق من المبرمجين و قام مبرمج آخر باستكمال العمل من بعدك حينها ستحتاج إلى منعه من عمل object بالطريقة العادية حتى لا تسبب مشاكل أثناء العمل؟ لكن كيف يتم ذلك ؟ كل ما عليك فعله هو أن تجعل الfunction التي تثوم بعمل الobject بطريقة عادية لتكون من نوع private و بالتالي لن يكون بالإمكان استدعاءها خارج الكلاس و سيكون المبرمج مجبرا على استخدام الfunction المسماة sharedObject و الآن هل انتهى الأمر ؟ نعم انتهى الأمر هنا و أصبح الsingleton object جاهزا للاستخدام أخيرا. بقي الإشارة إلى نقطة مهمة، إن كنت من مبرمجيswift المتمرسين، فلعلك لاحظت أن بعض الclasses التي تقوم باستخدامها هي في الحقيقة تطبق الsingleton pattern و من هذه الكلاسات : NSUserDefaults ----> var userDefaults = NSUserDefaults.standardUserDefaults() UIScreen ----> var mainSecreen = UIScreen.mainScreen UIApplication ----> var application = UIApplication.sharedApplication -- لاحظ أن الوصول للshared object يمكن أن يكون عن طريق static method كما شرحنا في هذا الدرس و قد يكون عن طريق static variable ختاما.. أتمنى أن أكون وفقت في الشرح و إيصال الفكرة و أسأل الله أن يجعله من العلم الذي يُنتفع به . تم ترقية هذا الطرح المميز الى صفحة المقالات
  11. بسم الله
  12. إصدار الxcode المستخدم : 8.0 لغة سويفت 3 في هذا الدرس سنتعلم طريقة إضافة خصائص إضافية في شريط الخصائص ( properties inspector ) في برنامج الxcode بطريقة سهلة و بسيطة حيث ستتمكن من إضافة مؤثرات بصرية إضافية لعناصر واجهة المستخدم كالحد (stroke or border ) و الزوايا الدائرية للأشكال.. مثلا سيكون بإمكانك عمل الظل و الحدود مع الزوايا الدائرية للview و ال label كما هو موضح في الصورة التالية. لاحظ وجود خيارات جديدة في الشريط الأيمن للتحكم بقيم الحد و الظل و الزوايا الدائرية إذن لنبدأ الدرس.. -في البداية.. قم بفتح الxcode و اختر create new xcode project ثم اختر single view application - قم بعمل كلاس جديد عن طريق File > New > File أو بالضغط على cmd+n ثم اختر cocoa touch class -قم بتسمية الclass بأي اسم يناسبك و تأكد من اختيار UIView عند Subclass of: كما هو موضح في الصورة ثم اضغط next الآن قم بإضافة IBDesignable قبل بداية التعريف بالكلاس في كلاس CustomizableView ليبدو بهذه الطريقة: import UIKit @IBDesignable class CustomizableView: UIView { } هذه الكلمة التي قمت بإضافتها تعطيك إمكانية ربط الكلاس مع الmain story board بحيث يقوم الاكس كود بمزامنة التغييرات التي تجريها على هذا الكلاس مع ال story board و إظهار النتائج مباشرة دون الحاجة إلى تشغيل الsimulator الاختبار النتيجة التي توصلت إليها الآن قم بإضافة الكود التالي إلى الكلاس.. @IBInspectable var cornerRadius:CGFloat = 0{ didSet{ self.layer.cornerRadius = cornerRadius } } -كما تلاحظ في البداية قمنا بإضافة @IBInspectable وهذه الكلمة تسبق المتغير الذي يحمل اسم cornerRadius و هذا أيضا يربط الكلاس مع الstory obard بطريقة أخرى بحيث يمكنك الآن التحكم بقيمة هذا المتغير من شريط الخصائص في الstory board مما سيؤدي إلى تغير قيمة هذا المتغير بناء على القيم المحددة في ال stroy board - بعد ذلك قمنا بإضافة المتغير cornerRadius و هو الذي سنستخدمه لتغيير الزوايا المنحنية في الview إلى زوايا دائرية و اخترنا نوع القيمة لتكون CGFloat و هو النوع المناسب لهذه الخاصية. - قمنا بإسناد القيمة 0 للمتغير كقيمة ابتدائية ثم بعد ذلك اضفنا الأقواس و هذه الأقواس تساعدك في إضافة تفاصيل أخرى للمتغير. - بداخل الأقواس قمنا بإضافة كلمة didSet متبوعة بأقواس و هذه الكلمة تمثل مجموعة من الأوامر يحددها المستخدم بحيث تطبق هذه الأوامر مباشرة بمجرد تغيير قيمة المتغير ، و هي يمكن تشبهها بالدالة function بحيث يقوم المبرمج بتحديد الأوامر التي ستوقوم هذه الدالة بها حالما يتم تغيير قيمة المتغير cornerRadius -اذن ما هي هذه الأوامر التي سيتم استدعاؤها ؟ self.layer.cornerRadius = cornerRadius كما هو موضح فإن self تمثل الاوبجكت من هذا الكلاس customizableView و بما أن هذا الكلاس يرث من الView فإنه سيرث خصائصها و التي منها layer ليقوم باستخدام الخاصية cornerRadius التي بداخل الlayer و التي تتحكم بمدى استدارة زوايا الشكل ثم يقوم بتغيير قيمتها لتساوي المتغير cornerRadius الذي نتحكم بقيمته من الstory board كما ذكرنا سابقا بفضل الخاصية @IBInspectable اذن مالذي سيحدث بالضبط؟ بمجرد إضافة عنصر view في الاكس كود و جعله يرث من الكلاس customizableView ستظهر لك الخواص المعروفة لهذا الview في شريط الخصائص كاللون و الحجم و المحاذاة ..الخ بالإضافة إلى خاصية مميزة جديدة لهذا الview فقط و هي الcornerRadius حيث ستظهر لك في شريط الخصائص بفضل كلمة @IBInspectable ثم سيكون بإمكانك تعديل قيمة ال cornerRadius و بمجرد تعديلها ستستدعى دالة didSet التي قمنا بإضافتها سابقا و بالتالي سيطبق أمر تغيير الcornerRadius الخاص بالشكل لتتغير قيمته من 0 إلى القيمة التي قمت بتحديدها له في شريط الخصائص و أخيرا سترى أن زوايا الview بالفعل أصبحت تتغير مباشرة و هذا بفضل كلمة @IBDesignable التي قمنا بإضافتها للكلاس customizableView لنطبق ذلك عمليا.. - قم بالذهاب إلى الstory board وإضافة view إليها و قم بتلوين هذا الview باللون الذي يناسبك. - الآن اذهب إلى الأيقونة التي بجانب أيقونة الخصائص و التي تسمى identity inspector و قم بتغيير الكلاس الخاص بالview إلى CustomizableView كما هو موضح في الصورة - انتظر قليلا ثم عد إلى الخصائص ستلاحظ و جود الخاصية الجديدة cornerRadius في أعلا شريط الخصائص كما هو واضح في الصورة.. - الآن قم بتغيير القيم لتلاحظ تغير زوايا الشكل بطريقة جميلة يمكنك إضافة المزيد من الخصائص التي بإمكانك التحكم بها بنفس الطريقة.. لإضافة خاصية الحد (border) : @IBInspectable var border:CGFloat = 0{ didSet{ self.layer.borderWidth = border } } لإضافة خاصية الظل ( لا أنصح بها لأنها قد تؤدي إلى بطء البرنامج بسبب معالجة الظل التي تستهلك الكثير من الأداء): @IBInspectable var shadow:CGFloat = 0{ didSet{ self.layer.shadowRadius = shadow } } @IBInspectable var opacity:Float = 0{ didSet{ self.layer.shadowOpacity = opacity/20 } } @IBInspectable var offset:CGFloat = 0{ didSet{ self.layer.shadowOffset.height = offset self.layer.shadowOffset.width = offset } } هذه الإضافات ليست خاصة للview فقط و إنما يمكنك إضافتها لأي عنصر رسومي في البرنامج فمثلا: بإمكانك فعل المثل للlabel كل ما عليك فعله : - قم بعمل كلاس جديد باسم customizableLabel على سبيل المثال - اجعله يرث من UILabel في خيار subclass of عند إنشاء الكلاس - قم بإضافة كلمة @IBDesignable عند بداية الكلاس -قم بنسخ نفس الكود الخاص بالcustomizableView و لصقه في كلاس customizableLabel - استمتع
  13. إصدار الxcode المستخدم : 8.0 لغة سويفت 3 في هذا الدرس سنتعلم طريقة إضافة خصائص إضافية في شريط الخصائص ( properties inspector ) في برنامج الxcode بطريقة سهلة و بسيطة حيث ستتمكن من إضافة مؤثرات بصرية إضافية لعناصر واجهة المستخدم كالحد (stroke or border ) و الزوايا الدائرية للأشكال.. مثلا سيكون بإمكانك عمل الظل و الحدود مع الزوايا الدائرية للview و ال label كما هو موضح في الصورة التالية. لاحظ وجود خيارات جديدة في الشريط الأيمن للتحكم بقيم الحد و الظل و الزوايا الدائرية إذن لنبدأ الدرس.. -في البداية.. قم بفتح الxcode و اختر create new xcode project ثم اختر single view application - قم بعمل كلاس جديد عن طريق File > New > File أو بالضغط على cmd+n ثم اختر cocoa touch class -قم بتسمية الclass بأي اسم يناسبك و تأكد من اختيار UIView عند Subclass of: كما هو موضح في الصورة ثم اضغط next الآن قم بإضافة IBDesignable قبل بداية التعريف بالكلاس في كلاس CustomizableView ليبدو بهذه الطريقة: import UIKit @IBDesignable class CustomizableView: UIView { } هذه الكلمة التي قمت بإضافتها تعطيك إمكانية ربط الكلاس مع الmain story board بحيث يقوم الاكس كود بمزامنة التغييرات التي تجريها على هذا الكلاس مع ال story board و إظهار النتائج مباشرة دون الحاجة إلى تشغيل الsimulator الاختبار النتيجة التي توصلت إليها الآن قم بإضافة الكود التالي إلى الكلاس.. @IBInspectable var cornerRadius:CGFloat = 0{ didSet{ self.layer.cornerRadius = cornerRadius } } -كما تلاحظ في البداية قمنا بإضافة @IBInspectable وهذه الكلمة تسبق المتغير الذي يحمل اسم cornerRadius و هذا أيضا يربط الكلاس مع الstory obard بطريقة أخرى بحيث يمكنك الآن التحكم بقيمة هذا المتغير من شريط الخصائص في الstory board مما سيؤدي إلى تغير قيمة هذا المتغير بناء على القيم المحددة في ال stroy board - بعد ذلك قمنا بإضافة المتغير cornerRadius و هو الذي سنستخدمه لتغيير الزوايا المنحنية في الview إلى زوايا دائرية و اخترنا نوع القيمة لتكون CGFloat و هو النوع المناسب لهذه الخاصية. - قمنا بإسناد القيمة 0 للمتغير كقيمة ابتدائية ثم بعد ذلك اضفنا الأقواس و هذه الأقواس تساعدك في إضافة تفاصيل أخرى للمتغير. - بداخل الأقواس قمنا بإضافة كلمة didSet متبوعة بأقواس و هذه الكلمة تمثل مجموعة من الأوامر يحددها المستخدم بحيث تطبق هذه الأوامر مباشرة بمجرد تغيير قيمة المتغير ، و هي يمكن تشبهها بالدالة function بحيث يقوم المبرمج بتحديد الأوامر التي ستوقوم هذه الدالة بها حالما يتم تغيير قيمة المتغير cornerRadius -اذن ما هي هذه الأوامر التي سيتم استدعاؤها ؟ self.layer.cornerRadius = cornerRadius كما هو موضح فإن self تمثل الاوبجكت من هذا الكلاس customizableView و بما أن هذا الكلاس يرث من الView فإنه سيرث خصائصها و التي منها layer ليقوم باستخدام الخاصية cornerRadius التي بداخل الlayer و التي تتحكم بمدى استدارة زوايا الشكل ثم يقوم بتغيير قيمتها لتساوي المتغير cornerRadius الذي نتحكم بقيمته من الstory board كما ذكرنا سابقا بفضل الخاصية @IBInspectable اذن مالذي سيحدث بالضبط؟ بمجرد إضافة عنصر view في الاكس كود و جعله يرث من الكلاس customizableView ستظهر لك الخواص المعروفة لهذا الview في شريط الخصائص كاللون و الحجم و المحاذاة ..الخ بالإضافة إلى خاصية مميزة جديدة لهذا الview فقط و هي الcornerRadius حيث ستظهر لك في شريط الخصائص بفضل كلمة @IBInspectable ثم سيكون بإمكانك تعديل قيمة ال cornerRadius و بمجرد تعديلها ستستدعى دالة didSet التي قمنا بإضافتها سابقا و بالتالي سيطبق أمر تغيير الcornerRadius الخاص بالشكل لتتغير قيمته من 0 إلى القيمة التي قمت بتحديدها له في شريط الخصائص و أخيرا سترى أن زوايا الview بالفعل أصبحت تتغير مباشرة و هذا بفضل كلمة @IBDesignable التي قمنا بإضافتها للكلاس customizableView لنطبق ذلك عمليا.. - قم بالذهاب إلى الstory board وإضافة view إليها و قم بتلوين هذا الview باللون الذي يناسبك. - الآن اذهب إلى الأيقونة التي بجانب أيقونة الخصائص و التي تسمى identity inspector و قم بتغيير الكلاس الخاص بالview إلى CustomizableView كما هو موضح في الصورة - انتظر قليلا ثم عد إلى الخصائص ستلاحظ و جود الخاصية الجديدة cornerRadius في أعلا شريط الخصائص كما هو واضح في الصورة.. - الآن قم بتغيير القيم لتلاحظ تغير زوايا الشكل بطريقة جميلة يمكنك إضافة المزيد من الخصائص التي بإمكانك التحكم بها بنفس الطريقة.. لإضافة خاصية الحد (border) : @IBInspectable var border:CGFloat = 0{ didSet{ self.layer.borderWidth = border } } لإضافة خاصية الظل ( لا أنصح بها لأنها قد تؤدي إلى بطء البرنامج بسبب معالجة الظل التي تستهلك الكثير من الأداء): @IBInspectable var shadow:CGFloat = 0{ didSet{ self.layer.shadowRadius = shadow } } @IBInspectable var opacity:Float = 0{ didSet{ self.layer.shadowOpacity = opacity/20 } } @IBInspectable var offset:CGFloat = 0{ didSet{ self.layer.shadowOffset.height = offset self.layer.shadowOffset.width = offset } } هذه الإضافات ليست خاصة للview فقط و إنما يمكنك إضافتها لأي عنصر رسومي في البرنامج فمثلا: بإمكانك فعل المثل للlabel كل ما عليك فعله : - قم بعمل كلاس جديد باسم customizableLabel على سبيل المثال - اجعله يرث من UILabel في خيار subclass of عند إنشاء الكلاس - قم بإضافة كلمة @IBDesignable عند بداية الكلاس -قم بنسخ نفس الكود الخاص بالcustomizableView و لصقه في كلاس customizableLabel - استمتع تم ترقية هذا الطرح المميز الى صفحة المقالات

عالم البرمجة

عالم البرمجة مقالات برمجة و دورات مجانية لإحتراف البرمجة هدفنا تبسيط البرمجة ونشرها بيد الكل بشكل ممتع ومتطور ومحدث بإستمرار لمواكبة جديد تطورات البرمجة الحديثة و المتقدمة بدون مقابل