AMR0T

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

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

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

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

4 Neutral

عن العضو AMR0T

  • الرتبه
    مبدع مثابر
  1. بسم الله الرحمن الرحيم مقدمة استعرضنا في الجزء الأول طريقة ارسال البيانات بين الViews عن طريق انشاء Reference للView المستقبلة للبيانات وتغيير قيم متغيراتها. في هذه المقالة، سنتعرف على ماهية البروتوكولات في سويفت وطريقة استخدامها لنقل البينات من أي View الى View اخر. أولا: ماهو البروتوكول لتفهم بالبروتوكول بشكل صحيح، فكر به على أنه طريقة لتعريف ما يمكن للمتغير أن يفعله، عكس الكلاسات التي تعرف ماهية المتغير. ثانيا: نقل البيانات بواسطة البروتوكول في الجزء الأول رأينا كيف نقوم بنقل البيانات بين الView Controllers الى الأمام، والآن سنستعمل البروتوكول لنقل البيانات للView السابقة سنقوم أولا بعمل السيت اب في الStoryboard كالتالي (سنسمي الView الأولى InitialVC والثانية FinalVC): والآن ضمًن الView الاولى بداخل Navigation Controller لتصبح كالتالي: سنقوم بانشاء Segue بين الView الأولى والثانية: قم باضافة زر لكل View كالتالي: لا تنسى اضافة الSegue identifier لأننا سنستعمله لاحقا والآن لننهي السيت أب، أضف الIBActions في الViewControllers لتصبح كالتالي: كل ماسبق كان مجرد تجهيز للتالي سنقوم الآن بتعريف البروتوكول والمتطلبات وانت في كلاس الFinalVC: قم باضافة تعريف للبروتوكول باعلى الصفحة يحتوي على ميثود finishPassing بباراميتر String قم بتعريف متغير delegate من نفس نوع البروتوكول في ميثود الIBAction، قم باستخدام المتغير لنقل البيانات التي تريد نقلها الى الView الأولى (في هذا المثال نقلت سترينق) سيصبح كلاس الFinalVC يبدو كالتالي: 1) أولا قمنا بانشاء بروتوكول (أو blueprint)، يحتوي على الميثود التي سنستعملها لاستقبال البيانات مستقبلا في الكلاس الأول 2) قمنا بانشاء متغير من نفس نوع البروتوكول ليحمل البيانات التي نريد ارسالها 3) عند الضغط على زر العودة، سنزود المتغير بالبيانات التي نريد نقلها الى الView الأولى الى الآن، المتغير delegate لا يعلم الى اي كلاس سيقوم بنقل البيانات التي يحملها معه سنقوم الآن بتبني البروتوكول في الكلاس الأول وتحديده كنقطة الوصول بالنسبة للمتغير وانت في كلاس الInitialVC: اضف البروتوكول الى الكلاس الأول لتبنيه اضف الميثود prepareForSegue واستخدمها لتحديد الكلاس الحالي كنقطة الوصول للمتغير delegate من الكلاس الأخير وأخيرا لتبني البروتوكول بشكل كامل وصحيح، أضف الميثود finishPassing واستخدمها للتعامل مع البيانات المنقولة من المتغير delegate سيصبح كلاس InitialVC يبدو كالتالي: 1) قمنا بتبني البروتوكول مبدئيا في الكلاس الأول 2) في الميثود prepareForSegue (التي سيتم استدعاءها قبل الانتقال الى الView الأخيرة)، قمنا باخبار المتغير delegate بان نقطة الوصول له هو الكلاس الحالي self 3) الى الآن ستلاحظ وجود error على الكلاس، لأنه يتوقع منك اضافة الميثود finishPassing التي ستتعامل مع البيانات التي ستصل من المتغير delegate، أضفناها وبداخلها طريقة للتعامل مع البيانات المنقولة عن طريق الparameter والآن أصبحنا جاهزين للتجربة لاحظ طباعة السترينق من الكلاس الأول كما حددنا في الميثود finishPassing، يمكنك أنت أن تقوم بالتعامل مع البيانات كما تشاء. وصلنا الى نهاية موضوعنا اليوم، أترككم في حفظ الله ورعايته.
  2. بسم الله الرحمن الرحيم سنتعرف في هذا الدرس على طريقة انشاء تطبيق يدعم تعدد اللغات بحسب لغة الجهاز، سنعتمد اللغتين العربية والانجليزية في هذا التطبيق. سنبدأ أولا باضافة جميع اللغات التي نريد دعمها في تطبيقنا نذهب الى Project Navigator ثم نقوم باضافة اللغات المطلوبة من الأسفل نلاحظ تقسيم الملفات الى لغتين كما في الصورة االآن سنقوم بانشاء ملف من نوع String لنخزن فيه جميع الStrings باللغتين العربية والانجليزية اضغط على File > New > File واختر النوع String كما في الصورة تأكد من تسمية الملف باسم "Localizable" تماما كما هو ليتعرف عليه الxCode بشكل صحيح الآن نختار الملف الجديد من اليسار، ومن قائمة الFile Inspector نضغط على Localize ونختار اللغة الانجليزية مبدئيا الآن نختار اللغة العربية أيضا لنقوم بتقسيم ملف الLocalizable.strings الى لغتين قم باضافة الStrings المطلوبة الى الملفين بالطريقة التالية ليقوم الxCode بعمل Build تأكد من: كتابة الkey بشكل موحد بين اللغتين العربية والانجليزية وضع علامة ال= بين الkey والvalue كتابة الvalue بين علامتي تنصيص "" انهاء السطر بSemi-Colon ; لنرى طريقة استدعاء الStrings من ملف Localizable قمت بعمل الواجهة البسيطة التالية: وقمت بربط الOutlets والActions كالتالي: الآن اضف الكود التالي في زر اللغة الانجليزية: let path = Bundle.main.path(forResource: "en", ofType: "lproj") let bundle = Bundle.init(path: path!)! as Bundle nameLbl.text = bundle.localizedString(forKey: "WebsiteName", value: nil, table: nil) والتالي لزر اللغة العربية: let path = Bundle.main.path(forResource: "ar", ofType: "lproj") let bundle = Bundle.init(path: path!)! as Bundle nameLbl.text = bundle.localizedString(forKey: "WebsiteName", value: nil, table: nil) في السطر الأول: قمنا بتعريف الpath الذي سيوصلنا لكل من ملفات اللغة العربية والانجليزية (يمكنك معرفة الResource والType من قائمة الFile Inspector عند الضغط على ملفي العربية والانجليزية) في السطر الثاني قمنا بتعريف كل من ملفات اللغتين كVariable يحمل الاسم bundle في السطر الثالث قمنا باستدعاء الString المطلوب باستخدام الميثود localizedString(_:String,_:String,_:Strint( والآن عند تجربة البرنامج نرى النتيجة التالية (صورة GIF): حتى الآن كنا نحدد ملف اللغة الذي نريد استدعاء الString منه والآن سنقوم بتغيير النص اعتمادا على لغة الجهاز باستخدام زر واحد فقط لنرى ذلك قمت بتغيير الStoryboard ليحتوي على زر واحد فقط، وقمت باضافة الoutlets والactions كالتالي: والآن قم باضافة السطرين التاليين للميثود viewDidLoad() let btnTitle: String = NSLocalizedString("ButtonText", comment: "") languageBtn.setTitle(btnTitle, for: .normal) والسطر التالي للميثود الخاصة بالbutton action nameLbl.text = NSLocalizedString("WebsiteName", comment: "") في هذه الاكواد، قمنا باستعمال الميثود NSLocalizedString لاستدعاء الString المناسب بحسب لغة الجهاز لتجربة البرنامج سنقوم بتشغيله على جهاز بلغة انجليزية، ثم سنحولها للعربية ونعيد التجربة (صورة GIF): وصلنا الى ختام الدرس، أستودعكم الله الذي لا تضيع ودائعه.
  3. بسم الله الرحمن الرحيم سنتعرف في هذا الدرس على طريقة انشاء تطبيق يدعم تعدد اللغات بحسب لغة الجهاز، سنعتمد اللغتين العربية والانجليزية في هذا التطبيق. سنبدأ أولا باضافة جميع اللغات التي نريد دعمها في تطبيقنا نذهب الى Project Navigator ثم نقوم باضافة اللغات المطلوبة من الأسفل نلاحظ تقسيم الملفات الى لغتين كما في الصورة االآن سنقوم بانشاء ملف من نوع String لنخزن فيه جميع الStrings باللغتين العربية والانجليزية اضغط على File > New > File واختر النوع String كما في الصورة تأكد من تسمية الملف باسم "Localizable" تماما كما هو ليتعرف عليه الxCode بشكل صحيح الآن نختار الملف الجديد من اليسار، ومن قائمة الFile Inspector نضغط على Localize ونختار اللغة الانجليزية مبدئيا الآن نختار اللغة العربية أيضا لنقوم بتقسيم ملف الLocalizable.strings الى لغتين قم باضافة الStrings المطلوبة الى الملفين بالطريقة التالية ليقوم الxCode بعمل Build تأكد من: كتابة الkey بشكل موحد بين اللغتين العربية والانجليزية وضع علامة ال= بين الkey والvalue كتابة الvalue بين علامتي تنصيص "" انهاء السطر بSemi-Colon ; لنرى طريقة استدعاء الStrings من ملف Localizable قمت بعمل الواجهة البسيطة التالية: وقمت بربط الOutlets والActions كالتالي: الآن اضف الكود التالي في زر اللغة الانجليزية: let path = Bundle.main.path(forResource: "en", ofType: "lproj") let bundle = Bundle.init(path: path!)! as Bundle nameLbl.text = bundle.localizedString(forKey: "WebsiteName", value: nil, table: nil) والتالي لزر اللغة العربية: let path = Bundle.main.path(forResource: "ar", ofType: "lproj") let bundle = Bundle.init(path: path!)! as Bundle nameLbl.text = bundle.localizedString(forKey: "WebsiteName", value: nil, table: nil) في السطر الأول: قمنا بتعريف الpath الذي سيوصلنا لكل من ملفات اللغة العربية والانجليزية (يمكنك معرفة الResource والType من قائمة الFile Inspector عند الضغط على ملفي العربية والانجليزية) في السطر الثاني قمنا بتعريف كل من ملفات اللغتين كVariable يحمل الاسم bundle في السطر الثالث قمنا باستدعاء الString المطلوب باستخدام الميثود localizedString(_:String,_:String,_:Strint( والآن عند تجربة البرنامج نرى النتيجة التالية GIF: والآن سنقوم بتغيير النص اعتمادا على لغة الجهاز باستخدام ميثود واحدة فقط لنرى ذلك قمت بتغيير الStoryboard ليحتوي على زر واحد فقط، وقمت باضافة الoutlets والactions كالتالي: والآن قم باضافة السطرين التاليين للميثود viewDidLoad() let btnTitle: String = NSLocalizedString("ButtonText", comment: "") languageBtn.setTitle(btnTitle, for: .normal) والسطر التالي للميثود الخاصة بالbutton action nameLbl.text = NSLocalizedString("WebsiteName", comment: "") في هذه الاكواد، قمنا باستعمال الميثود NSLocalizedString لاستدعاء الString المناسب بحسب لغة الجهاز لتجربة البرنامج سنقوم بتشغيله على جهاز بلغة انجليزية، ثم سنحولها للعربية ونعيد التجربة وصلنا الى ختام الدرس، أستودعكم الله الذي لا تضيع ودائعه. تم ترقية هذا الطرح المميز الى صفحة المقالات
  4. بسم الله الرحمن الرحيم مقدمة عادة يتم استخدام الUIAlertController لعرض نافذة تحذيرية للمستخدم، تحتوي على رسالة وازرار لاتخاذ اجراءات بناء عليها. يمكن استخدامها أيضا لتمكين المستخدم من ادخال بيانات تسجيل دخول او حساب جديد، عرض بيانات للمستخدم، أو عرض المزيد من الاعدادات في نافذة خارجية. منذ قدوم iOS9، أبل قامت بالغاء الكلاس القديم UIAlertView واستبدلته بUIAlertController، حيث لم تعد تحتاج لضبط الdelegatesـ وتستطيع الآن تخصيص النافذة كما تشاء. هناك نوعين من الUIAlertController: 1- Alert UIAlertController 2- ActionSheet UIAlertController والآن سنرى كيفية انشائها وتخصيصها (لانشاء النوافذ المطلوبة، يمكنك تضمين جميع الأكواد القادمة في داخل IBAction او TableViewCell أو حتى في viewDidLoad لتقوم بتنفيذ الكود مباشرة) - نافذة Alert تحتوي على TextField: أول نافذة تحذيرية سنقوم بانشائها، تحتوي على textfield واحد، بالاضافة الى زرين submit و cancel سنبدأ أولا باضافة الأسطر التالية: let alert = UIAlertController(title: "AlertController Tutorial", message: "Submit some text", preferredStyle: .alert) // Submit button let submitAction = UIAlertAction(title: "Submit", style: .default, handler: { (action) -> Void in // Get 1st TextField's text let textField = alert.textFields![0] print(textField.text!) }) // Cancel button let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in }) في الثلاث أسطر الأولى، قمنا بانشاء UIAlertController، وحددنا عنوانه والرسالة المضمنة فيه، وحددنا نوعه ليكون alert. تاليا قمنا بانشاء أول زر submitAction، وخصصنا عنوانه وستايله، وفي بلوك الhandler الأخير أضفنا الأوامر التي نرغب بتنفيذها عند الضغط على هذا الزر أخيرا قمنا بانشاء زر cancel بستايل destructive. ليكون أحمر اللون الآن بقي لنا أن نضيف هذين الزرين الى النافذة التي أنشأناها أولا، ومن ثم نعرض النافذة للمستخدم. ولكن قبل هذا، لا ننسى أن ننشئ و نضيف الTextField الى النافذة، فنكمل باضافة الكود التالي: // Add 1 textField and customize it alert.addTextField { (textField: UITextField) in textField.keyboardAppearance = .dark textField.keyboardType = .default textField.autocorrectionType = .default textField.placeholder = "Type something here" textField.clearButtonMode = .whileEditing } // Add action buttons and present the Alert alert.addAction(submitAction) alert.addAction(cancel) present(alert, animated: true, completion: nil) في الأسطر الأولى قمنا بانشاء وتخصيص واضافة الTextField في خطوة واحدة. ثم أخيرا قمنا باضافة الزرين السابق انشاؤهما وقمنا بعرض الUIAlertController عن طريق استدعاء الميثود present النتيجة: - نافذة ActionSheet تحتوي على عدة خيارات: بطريقة مشابهة جدا لنوافذ الAlert، سنقوم بانشاء نافذة ActionSheet. أولا سنقوم باضافة الكود التالي: let alertController = UIAlertController(title: "Action Sheet", message: "What would you like to do?", preferredStyle: .actionSheet) let sendButton = UIAlertAction(title: "Send", style: .default, handler: { (action) -> Void in print("Send button tapped") }) let deleteButton = UIAlertAction(title: "Delete", style: .destructive, handler: { (action) -> Void in print("Delete button tapped") }) let cancelButton = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in print("Cancel button tapped") }) قمنا أولا بانشاء UIAlertController من نوع ActionSheet، ثم أنشأنا عدة أزرار بستايلات مختلفة وكل زر يحتوي على بلوك الactions الخاص به. الآن سنضيف الأزرار الى الUIAlertController ومن ثم سنعرضها: alertController.addAction(sendButton) alertController.addAction(deleteButton) alertController.addAction(cancelButton) present(alertController, animated: true, completion: nil) النتيجة: لاحظ أن ستايلات الأزرار تختلف بالشكل: defaults. يعطيك شكل زر Send now الطبيعي destructive. يضيف اللون الأحمر ويستعمل عادة لأوامر الحذف لتنبيه المستخدم cancel. يعزل الزر عن باقي الأزرار ويستعمل عادة لزر الالغاء وهنا نصل الى ختام موضوعنا، نلقاكم على خير باذن الله سبحانك اللهم وبحمدك أشهد أن لا اله إلا أنت، استغفرك وأتوب اليك
  5. بسم الله الرحمن الرحيم مقدمة عادة يتم استخدام الUIAlertController لعرض نافذة تحذيرية للمستخدم، تحتوي على رسالة وازرار لاتخاذ اجراءات بناء عليها. يمكن استخدامها أيضا لتمكين المستخدم من ادخال بيانات تسجيل دخول او حساب جديد، عرض بيانات للمستخدم، أو عرض المزيد من الاعدادات في نافذة خارجية. منذ قدوم iOS9، أبل قامت بالغاء الكلاس القديم UIAlertView واستبدلته بUIAlertController، حيث لم تعد تحتاج لضبط الdelegatesـ وتستطيع الآن تخصيص النافذة كما تشاء. هناك نوعين من الUIAlertController: 1- Alert UIAlertController 2- ActionSheet UIAlertController والآن سنرى كيفية انشائها وتخصيصها (لانشاء النوافذ المطلوبة، يمكنك تضمين جميع الأكواد القادمة في داخل IBAction او TableViewCell أو حتى في viewDidLoad لتقوم بتنفيذ الكود مباشرة) - نافذة Alert تحتوي على TextField: أول نافذة تحذيرية سنقوم بانشائها، تحتوي على textfield واحد، بالاضافة الى زرين submit و cancel سنبدأ أولا باضافة الأسطر التالية: let alert = UIAlertController(title: "AlertController Tutorial", message: "Submit some text", preferredStyle: .alert) // Submit button let submitAction = UIAlertAction(title: "Submit", style: .default, handler: { (action) -> Void in // Get 1st TextField's text let textField = alert.textFields![0] print(textField.text!) }) // Cancel button let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: { (action) -> Void in }) في الثلاث أسطر الأولى، قمنا بانشاء UIAlertController، وحددنا عنوانه والرسالة المضمنة فيه، وحددنا نوعه ليكون alert. تاليا قمنا بانشاء أول زر submitAction، وخصصنا عنوانه وستايله، وفي بلوك الhandler الأخير أضفنا الأوامر التي نرغب بتنفيذها عند الضغط على هذا الزر أخيرا قمنا بانشاء زر cancel بستايل destructive. ليكون أحمر اللون الآن بقي لنا أن نضيف هذين الزرين الى النافذة التي أنشأناها أولا، ومن ثم نعرض النافذة للمستخدم. ولكن قبل هذا، لا ننسى أن ننشئ و نضيف الTextField الى النافذة، فنكمل باضافة الكود التالي: // Add 1 textField and customize it alert.addTextField { (textField: UITextField) in textField.keyboardAppearance = .dark textField.keyboardType = .default textField.autocorrectionType = .default textField.placeholder = "Type something here" textField.clearButtonMode = .whileEditing } // Add action buttons and present the Alert alert.addAction(submitAction) alert.addAction(cancel) present(alert, animated: true, completion: nil) في الأسطر الأولى قمنا بانشاء وتخصيص واضافة الTextField في خطوة واحدة. ثم أخيرا قمنا باضافة الزرين السابق انشاؤهما وقمنا بعرض الUIAlertController عن طريق استدعاء الميثود present النتيجة: - نافذة ActionSheet تحتوي على عدة خيارات: بطريقة مشابهة جدا لنوافذ الAlert، سنقوم بانشاء نافذة ActionSheet. أولا سنقوم باضافة الكود التالي: let alertController = UIAlertController(title: "Action Sheet", message: "What would you like to do?", preferredStyle: .actionSheet) let sendButton = UIAlertAction(title: "Send", style: .default, handler: { (action) -> Void in print("Send button tapped") }) let deleteButton = UIAlertAction(title: "Delete", style: .destructive, handler: { (action) -> Void in print("Delete button tapped") }) let cancelButton = UIAlertAction(title: "Cancel", style: .cancel, handler: { (action) -> Void in print("Cancel button tapped") }) قمنا أولا بانشاء UIAlertController من نوع ActionSheet، ثم أنشأنا عدة أزرار بستايلات مختلفة وكل زر يحتوي على بلوك الactions الخاص به. الآن سنضيف الأزرار الى الUIAlertController ومن ثم سنعرضها: alertController.addAction(sendButton) alertController.addAction(deleteButton) alertController.addAction(cancelButton) present(alertController, animated: true, completion: nil) النتيجة: لاحظ أن ستايلات الأزرار تختلف بالشكل: defauls. يعطيك شكل زر Send now الطبيعي destructive. يضيف اللون الأحمر ويستعمل عادة لأوامر الحذف لتنبيه المستخدم cancel. يعزل الزر عن باقي الأزرار ويستعمل عادة لزر الالغاء وهنا نصل الى ختام موضوعنا، نلقاكم على خير باذن الله سبحانك اللهم وبحمدك أشهد أن لا اله إلا أنت، استغفرك وأتوب اليك
  6. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في أغلب الأحيان، عندما تقوم بتصميم برنامج يحتوي على أكثر من شاشة View Controller، ستحتاج لإرسال البيانات من شاشة لأخرى (سواء للأمام أو الخلف) ليكتمل تصميم البرنامج. في هذه المقالة، سنستعرض احدى اسهل الطرق لارسال البيانات من شاشة الى شاشة تالية، سنسرسل بيانات من انواع مختلفة String, Int, UIImage. أولا/ بناء المشروع 1: قم بانشاء مشروع جديد من نوع Single View Application بأي اسم ترغبه 2: أضف View Controller جديدة الى الStoryboard 3: قم بتحديد الView Controller الأولى واختر Embed In > Navigation Controller 4: أضف الأدوات المطلوبة (Text Field, Image View, Button) كما في الصورة 5: أنشئ ملف Cocoa Touch Class جديد باسم SecondVC واضفه الى الView Controller الثانية عند الضغط على الView Controller الثانية، تأكد من اضافة "SecondVC" في خانتي الClass والStoryboard ID كما في الصورة التالية 6: لإضافة الIBOutlets للView Controller الأولى قم بفتح الAssistant Editor للStoryboard والViewController.swift 7: مع الضغط على control، قم بسحب الأدوات الى الأيمن واضافتها كIBOutlets : (صورة متحركة، قم بالنقر عليها لمشاهدة الAnimation) 8: عند اضافة الButton تأكد من اضافته كAction وليس كOutlet 9: الآن قم بعمل نفس الشيء مع الشاشة الأخرى، واضف الImage والLabel كOutlets ثانيا/ كتابة الكود أولا قم باضافة التعديلات التالية على الكلاس الثاني (SecondVC) كما في الصورة قمنا بانشاء متغيرات في الكلاس الثاني، لتكون مستعدة لاستقبال البيانات من الكلاس الأول وحالما يبدأ عرض الشاشة، سيقوم السطرين المضافين الى الميثود ()viewDidLoad بعرض هذه البيانات الى المستخدم الآن، قم باضافة الكود التالي في داخل الميثود ()sendBtnTapped في الكلاس الأول let myVC = storyboard?.instantiateViewController(withIdentifier: "SecondVC") as! SecondVC myVC.stringPassed = textField.text! myVC.imagePassed = imageView.image! navigationController?.pushViewController(myVC, animated: true) في السطر الأول، قمنا بانشاء instance جديدة من الView Controller الثانية في السطر الثاني والثالث، استخدمنا هذه الinstance لتمرير المعلومات من الكلاس الأول الى المتغيرات التي أنشأناها في الكلاس الثاني وأخيرا في السطر الرابع، قمنا بطلب الانتقال من الشاشة الأولى الى الشاشة الثانية (أو بمعنى أدق، عرض الشاشة الثانية فوق الشاشة الأولى) بقي أن تضيف صورة الى الUIImageView في الشاشة الأولى باستخدام الStoryboard قمت أنا باضافة لوقو أبل كصورة تجريبية: الآن قم بتشغيل البرنامج، وأضف اي نص في الText Field واضغط على الزر لمشاهدة النتيجة: (صورة متحركة، قم بالنقر عليها لمشاهدة الAnimation) في الجزء الثاني سنتعرف بإذن الله على طريقة أخرى لارسال البيانات من كلاس لآخر. بحفظ الله ورعايته.
  7. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في أغلب الأحيان، عندما تقوم بتصميم برنامج يحتوي على أكثر من شاشة View Controller، ستحتاج لإرسال البيانات من شاشة لأخرى (سواء للأمام أو الخلف) ليكتمل تصميم البرنامج. في هذه المقالة، سنستعرض احدى اسهل الطرق لارسال البيانات من شاشة الى شاشة تالية، سنسرسل بيانات من انواع مختلفة String, Int, UIImage. أولا/ بناء المشروع 1: قم بانشاء مشروع جديد من نوع Single View Application بأي اسم ترغبه 2: أضف View Controller جديدة الى الStoryboard 3: قم بتحديد الView Controller الأولى واختر Embed In > Navigation Controller 4: أضف الأدوات المطلوبة (Text Field, Image View, Button) كما في الصورة 5: أنشئ ملف Cocoa Touch Class جديد باسم SecondVC واضفه الى الView Controller الثانية عند الضغط على الView Controller الثانية، تأكد من اضافة "SecondVC" في خانتي الClass والStoryboard ID كما في الصورة التالية 6: لإضافة الIBOutlets للView Controller الأولى قم بفتح الAssistant Editor للStoryboard والViewController.swift 7: مع الضغط على control، قم بسحب الأدوات الى الأيمن واضافتها كIBOutlets : (صورة متحركة، قم بالنقر عليها لمشاهدة الAnimation) 8: عند اضافة الButton تأكد من اضافته كAction وليس كOutlet 9: الآن قم بعمل نفس الشيء مع الشاشة الأخرى، واضف الImage والLabel كOutlets ثانيا/ كتابة الكود أولا قم باضافة التعديلات التالية على الكلاس الثاني (SecondVC) كما في الصورة قمنا بانشاء متغيرات في الكلاس الثاني، لتكون مستعدة لاستقبال البيانات من الكلاس الأول وحالما يبدأ عرض الشاشة، سيقوم السطرين المضافين الى الميثود ()viewDidLoad بعرض هذه البيانات الى المستخدم الآن، قم باضافة الكود التالي في داخل الميثود ()sendBtnTapped في الكلاس الأول let myVC = storyboard?.instantiateViewController(withIdentifier: "SecondVC") as! SecondVC myVC.stringPassed = textField.text! myVC.imagePassed = imageView.image! navigationController?.pushViewController(myVC, animated: true) في السطر الأول، قمنا بانشاء instance جديدة من الView Controller الثانية في السطر الثاني والثالث، استخدمنا هذه الinstance لتمرير المعلومات من الكلاس الأول الى المتغيرات التي أنشأناها في الكلاس الثاني وأخيرا في السطر الرابع، قمنا بطلب الانتقال من الشاشة الأولى الى الشاشة الثانية (أو بمعنى أدق، عرض الشاشة الثانية فوق الشاشة الأولى) بقي أن تضيف صورة الى الUIImageView في الشاشة الأولى باستخدام الStoryboard قمت أنا باضافة لوقو أبل كصورة تجريبية: الآن قم بتشغيل البرنامج، وأضف اي نص في الText Field واضغط على الزر لمشاهدة النتيجة: (صورة متحركة، قم بالنقر عليها لمشاهدة الAnimation) في الجزء الثاني سنتعرف بإذن الله على طريقة أخرى لارسال البيانات من كلاس لآخر. بحفظ الله ورعايته. تم ترقية هذا الطرح المميز الى صفحة المقالات
  8. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذا الموضوع، سنستعرض الStreams، وهي عبارة عن API جديدة ورائعه تم اضافتها في التحديث الأخير للJava 8. باستخدام الStreams، ستستطيع معالجة بيانات الCollections كأنك تقوم بعمل Query في احد الSQL databases، وذلك بطريقة تعريفية بسيطة دون الحاجة لكتابة Loop في كل مرة تريد معالجة البيانات لتخرج بنتيجة معينة (جمع عناصر الArrayList على سبيل المثال)، وذلك بكتابة سطر برمجي واحد فقط! هناك ميزة أخرى أيضا للStreams، وهي امكانية تفعيل جميع أنوية المعالج لتسريع عملية تنفيذ البرنامج دون الحاجة الى كتابة سطر واحد من كلاس الThreads المزعج! ما هو الStream؟ سنذكر تاليا أهم سمات الStream في الجافا: تسلسل عناصر: الStream هو عبارة عن تسلسل لعناصر يتم استخلاصها من أحد المصادر (Sources) -قد تكون Array أو ArrayList الخ-، حيث يقوم الStream بـ قراءة/معالجة بيانات هذه المصادر عند الحاجة فقط المصادر: قد تكون Collection, Arrays, I/O العمليات: يدعم الStream مجموعة من العمليات (أو methods) على سبيل المثال لا الحصر: filter, map, limit, reduce, find, match تكرارات تلقائية: الStreams تدعم التكرارات التلقائية (Automatic Iterations)، أي كما قلنا سابقا، لن تكتب المزيد من الloops، كل ماعليك فعله هو كتابة سطر واحد باستعمال الStreams والجافا ستقوم بالباقي إنشاء الStream في الجافا 8، هناك طريقتان لإنشاء Stream: ()stream: ستنشئ ستريم تسلسلي مربوط بcollection، ولكن بدون الاستفادة من ميزة تعدد أنوية المعالج في التنفيذ ()parallelStream: ستنشئ ستريم متوازي مربوط بcollection، مستفيدًا من ميزة تعدد أنوية المعالج في التنفيذ مثال: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); أهم ميثودز الStream ()forEach: هذه الميثود تعطيك امكانية المرور بجميع عناصر الستريم للقيام بعملية معينة، في المثال التالي سنقوم بطباعة 10 ارقام عشوائية باستخدام forEach: Random random = new Random(); random.ints().limit(10).forEach(System.out::println); ()map: بهذه الميثود تستخدم لربط كل عنصر بالستريم مع نتيجة خاصة به. في المثال التالي سنقوم بطباعة مربعات ارقام مميزة باستخدام map: List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of unique squares List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); ()filter: يتم استخدام هذه الميثود للتخلص من بعض عناصر الستريم بناء على شروط معينة، المثال التالي يقوم بطباعة عدد ال Strings الفارغة: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.stream().filter(string -> string.isEmpty()).count(); ()limit: هذه الميثود تستخدم للحد من حجم الستريم بدون أي شروط، في المثال التالي سنقوم بطباعة 10 ارقام عشوائية باستخدام limit: Random random = new Random(); random.ints().limit(10).forEach(System.out::println); ()sorted: يتم استخدام هذه الميثود لترتيب الستريم، الكود التالي يظهر كيف تقوم بطباعة 10 ارقام عشوائية مرتبة: Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println); ( لاحظ كيف أنجزنا المهمة بسطر واحد فقط، تخيل لو أردت أن تقوم بطباعة 10 ارقام عشوائية مرتبة بالطريقة التقليدية! ) Parallel Processing: هذه هي الطريقة الثانية لإنشاء الستريم الموازي (استعمال جميع أنوية المعالج لتنفيذ البرنامج) كما هو مذكور بالأعلى: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.parallelStream().filter(string -> string.isEmpty()).count(); لاحظ أنك تستطيع التبديل بين الStream والparallelStream بسهولة تامة. Collectors: نستخدم الCollectors لجمع نتائج معالجة بيانات الستريم واعادتها على شكل List. List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered List: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString); في المثال التالي، سنقوم بعمل مقارنة بين الJava 7 والJava 8 في برنامج يقوم بضم الStrings غير الفارغة. import java.util.*; public class Java8StreamTest { public static void main(String[] args) { // Java 7 approach System.out.println("Using Java 7: "); List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); System.out.println("List: " +strings); StringBuilder stringBuilder = new StringBuilder(); for (String string: strings) { if (!string.isEmpty()) { stringBuilder.append(string); stringBuilder.append(", "); } } String mergedString = stringBuilder.toString(); System.out.println("Merged String: " + mergedString); // Java 8 approach System.out.println("Using Java 8: "); System.out.println("List: " +strings); mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString); } } وهنا نصل الى ختام موضوعنا، أسأل الله لي ولكم التوفيق والسداد.
  9. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذا الموضوع، سنستعرض الStreams، وهي عبارة عن API جديدة ورائعه تم اضافتها في التحديث الأخير للJava 8. باستخدام الStreams، ستستطيع معالجة بيانات الCollections كأنك تقوم بعمل Query في احد الSQL databases، وذلك بطريقة تعريفية بسيطة دون الحاجة لكتابة Loop في كل مرة تريد معالجة البيانات لتخرج بنتيجة معينة (جمع عناصر الArrayList على سبيل المثال)، وذلك بكتابة سطر برمجي واحد فقط! هناك ميزة أخرى أيضا للStreams، وهي امكانية تفعيل جميع أنوية المعالج لتسريع عملية تنفيذ البرنامج دون الحاجة الى كتابة سطر واحد من كلاس الThreads المزعج! ما هو الStream؟ سنذكر تاليا أهم سمات الStream في الجافا: تسلسل عناصر: الStream هو عبارة عن تسلسل لعناصر يتم استخلاصها من أحد المصادر (Sources) -قد تكون Array أو ArrayList الخ-، حيث يقوم الStream بـ قراءة/معالجة بيانات هذه المصادر عند الحاجة فقط المصادر: قد تكون Collection, Arrays, I/O العمليات: يدعم الStream مجموعة من العمليات (أو methods) على سبيل المثال لا الحصر: filter, map, limit, reduce, find, match تكرارات تلقائية: الStreams تدعم التكرارات التلقائية (Automatic Iterations)، أي كما قلنا سابقا، لن تكتب المزيد من الloops، كل ماعليك فعله هو كتابة سطر واحد باستعمال الStreams والجافا ستقوم بالباقي إنشاء الStream في الجافا 8، هناك طريقتان لإنشاء Stream: ()stream: ستنشئ ستريم تسلسلي مربوط بcollection، ولكن بدون الاستفادة من ميزة تعدد أنوية المعالج في التنفيذ ()parallelStream: ستنشئ ستريم متوازي مربوط بcollection، مستفيدًا من ميزة تعدد أنوية المعالج في التنفيذ مثال: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); أهم ميثودز الStream ()forEach: هذه الميثود تعطيك امكانية المرور بجميع عناصر الستريم للقيام بعملية معينة، في المثال التالي سنقوم بطباعة 10 ارقام عشوائية باستخدام forEach: Random random = new Random(); random.ints().limit(10).forEach(System.out::println); ()map: بهذه الميثود تستخدم لربط كل عنصر بالستريم مع نتيجة خاصة به. في المثال التالي سنقوم بطباعة مربعات ارقام مميزة باستخدام map: List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of unique squares List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList()); ()filter: يتم استخدام هذه الميثود للتخلص من بعض عناصر الستريم بناء على شروط معينة، المثال التالي يقوم بطباعة عدد ال Strings الفارغة: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.stream().filter(string -> string.isEmpty()).count(); ()limit: هذه الميثود تستخدم للحد من حجم الستريم بدون أي شروط، في المثال التالي سنقوم بطباعة 10 ارقام عشوائية باستخدام limit: Random random = new Random(); random.ints().limit(10).forEach(System.out::println); ()sorted: يتم استخدام هذه الميثود لترتيب الستريم، الكود التالي يظهر كيف تقوم بطباعة 10 ارقام عشوائية مرتبة: Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println); ( لاحظ كيف أنجزنا المهمة بسطر واحد فقط، تخيل لو أردت أن تقوم بطباعة 10 ارقام عشوائية مرتبة بالطريقة التقليدية! ) Parallel Processing: هذه هي الطريقة الثانية لإنشاء الستريم الموازي (استعمال جميع أنوية المعالج لتنفيذ البرنامج) كما هو مذكور بالأعلى: List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); //get count of empty string int count = strings.parallelStream().filter(string -> string.isEmpty()).count(); لاحظ أنك تستطيع التبديل بين الStream والparallelStream بسهولة تامة. Collectors: نستخدم الCollectors لجمع نتائج معالجة بيانات الستريم واعادتها على شكل List. List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered List: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString); في المثال التالي، سنقوم بعمل مقارنة بين الJava 7 والJava 8 في برنامج يقوم بضم الStrings غير الفارغة. import java.util.*; public class Java8StreamTest { public static void main(String[] args) { // Java 7 approach System.out.println("Using Java 7: "); List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); System.out.println("List: " +strings); StringBuilder stringBuilder = new StringBuilder(); for (String string: strings) { if (!string.isEmpty()) { stringBuilder.append(string); stringBuilder.append(", "); } } String mergedString = stringBuilder.toString(); System.out.println("Merged String: " + mergedString); // Java 8 approach System.out.println("Using Java 8: "); System.out.println("List: " +strings); mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Merged String: " + mergedString); } } وهنا نصل الى ختام موضوعنا، أسأل الله لي ولكم التوفيق والسداد. تم ترقية هذا الطرح المميز الى صفحة المقالات
  10. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذا الدرس سنتعرف على احد أهم الأنواع في الSwift الا وهما Structures and Enumerations. أولا: Structures أو struct في Swift او اي لغة برمجة مشابهة، تعتبر الكلاسات حجر الأساس لمبدأ الObject-Oriented Programming. بالإضافة الى الكلاسات، لدينا الStructures التي تعطينا بديل مشابه للكلاسات. الستركتشر مشابه للكلاس، لأنه يمكن أن يحتوي على methods, properties, initializers تماما كما الكلاس، ولكن الفارق الأساسي هو ان الستركتشر يعتبر من نوع Value، والكلاسات تعتبر من نوع Reference. ما معنى Value type و Reference type؟ صورة توضيحية للفرق بين الRegerence والValue جميع الأنواع في الSwift هي اما عبارة عن Value type او Reference type. المتغيرات من نوع القيمة (Value type) -مثل متغيرات الInt والBool-، تقوم بنسخ قيمتها عندما يتم مساواتها بمتغير آخر بينما متغيرات نوع المرجع (Reference type) -مثل أي اوبجكت من كلاس-، تقوم باعارة قيمتها عندما يتم مساواتها بمتغير آخر. لنشرح الفرق بينهم سنطرح هذا المثال البسيط لنوع القيمة: var a: Int var b: Int a=5 b=a a=10 print(a) print(b) في المثال السابق، سيتم طباعة قيمتين مختلفتين لكل من a=10 و b=5، لأن قيمة a نسخت في البداية الى b حتى أصبح كل متغير يحمل قيمة خاصة ومستقلة عن المتغير الآخر، وعند تغيير قيمة a لم تتأثر قيمة b بذلك. ولنوع المرجع لنرى المثال التالي: var a = Car() var b: Car b = a a.startCar() b.printCarStatus() في المثال السابق، اذا طبقنا هذا الكود فسنلاحظ أن متغير السيارة b يعمل بالفعل، أي أن قيمة a اعيرت الى b، بحيث أي تغيير يطرأ على a سيؤثر بb، وأي تغيير يطرأ على b سيؤثر بa. اذا من المهم جدا أن نتذكر بأن الStructures من نوع القيمة (Value type)، بينما الClasses من نوع المرجع (Reference type). اختلاف آخر صغير بين الستركتشرز والكلاسات، أن الproperties في الستركتشر لا يمكن تعديلها بطريقة مباشرة من الميثودز، بل يجب استعمال كلمة mutator لكل ميثود كي نستطيع تعديل الproperties. مثال: struct Circle { var centerX = 0.0, centerY = 0.0, radius = 1.0 mutating func doubleRadius() { radius = radius * 2 } } اذا أردنا مضاعفة قيمة الradius من داخل الفنكشن doubleRadius، فسنضطر لاستخدام كلمة mutator قبل الميثود، دلالة على تغيير المتغير radius بقيمة أخرى دون الحاجة لنسخه. فيما عدا ذلك، فإن الستركتشرز تعتبر مشابهة تماما للكلاسات. ثانيا: Enumerations او enum التعدادات (Enumerations) هي طريقة نستطيع من خلالها أن نجمع العديد من قيم المتغيرات المرتبطة ببعضها. وكما الستركتشرز، فان التعدادات تعتبر من انواع القيمة (Value type). لنفترض بأننا نريد أن نعرف مجموعة الكواكب الشمسية، بدون استخدام التعدادات سنقوم بكتابة كود مشابه للتالي: let mercury = 1 let venus = 2 let earth = 3 ... وبهذه الحالة سنضطر لاضاعة أسطر أخرى للتأكد من الادخال الصحيح، فمثلا لو أدخل احدهم الرقم -1: var currentPlanet = -1 // not a valid planet! فسيكون هناك خطأ أنتاء عمل البرنامج، ان لم نقم بكتابة if-statements مناسبة ولكن في حالة التعدادات، يمكننا كتابتها كالتالي: enum Planet { case mercury = 1 case venus = 2 case earth = 3 case mars = 4 case jupiter = 5 case saturn = 6 case uranus = 7 } او اختصارا: enum Planet { case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune } والآن، ان تم ادخال قيمة غير صحيحة: var currentPlanet = Planet.mercury currentPlanet = -1 // error! فسنتعرف على الخطأ مباشرة. في هذا المثال سنرى امكانية تخزين قيم مختلفة لكل case لاحقا، الآن لننشئ مجموعة الألوان الخاصة بنا: enum Color { case rgb(Int, Int, Int) case argb(Int, Int, Int, Int) case cmyk(Int, Int, Int, Int) case name(String) } عند كتابة الenum بهذه الطريقة، فكأننا نخبر الSwift بأن كل case ستحصل على قيم خاصة بها لاحقا، مثل: var blue = Color.rgb(0, 0, 255) ويمكن استعمال الاختصار التالي عند تغيير قيمة المتغير: var blue = Color.rgb(0, 0, 255) blue = .argb(100, 0, 0, 255) blue = .name("blue") فبعد المساواة الأولى، أصبح من المعروف أن المتغير blue لن يخرج عن أحد خيارات المتعدد Color. وهنا نصل الى ختام موضوعنا، تقبل الله منا ومنكم صالح الأعمال والسلام عليكم ورحمة الله
  11. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته في هذا الدرس سنتعرف على احد أهم الأنواع في الSwift الا وهما Structures and Enumerations. أولا: Structures أو struct في Swift او اي لغة برمجة مشابهة، تعتبر الكلاسات حجر الأساس لمبدأ الObject-Oriented Programming. بالإضافة الى الكلاسات، لدينا الStructures التي تعطينا بديل مشابه للكلاسات. الستركتشر مشابه للكلاس، لأنه يمكن أن يحتوي على methods, properties, initializers تماما كما الكلاس، ولكن الفارق الأساسي هو ان الستركتشر يعتبر من نوع Value، والكلاسات تعتبر من نوع Reference. ما معنى Value type و Reference type؟ صورة توضيحية للفرق بين الRegerence والValue جميع الأنواع في الSwift هي اما عبارة عن Value type او Reference type. المتغيرات من نوع القيمة (Value type) -مثل متغيرات الInt والBool-، تقوم بنسخ قيمتها عندما يتم مساواتها بمتغير آخر بينما متغيرات نوع المرجع (Reference type) -مثل أي اوبجكت من كلاس-، تقوم باعارة قيمتها عندما يتم مساواتها بمتغير آخر. لنشرح الفرق بينهم سنطرح هذا المثال البسيط لنوع القيمة: var a: Int var b: Int a=5 b=a a=10 print(a) print(b) في المثال السابق، سيتم طباعة قيمتين مختلفتين لكل من a=10 و b=5، لأن قيمة a نسخت في البداية الى b حتى أصبح كل متغير يحمل قيمة خاصة ومستقلة عن المتغير الآخر، وعند تغيير قيمة a لم تتأثر قيمة b بذلك. ولنوع المرجع لنرى المثال التالي: var a = Car() var b: Car b = a a.startCar() b.printCarStatus() في المثال السابق، اذا طبقنا هذا الكود فسنلاحظ أن متغير السيارة b يعمل بالفعل، أي أن قيمة a اعيرت الى b، بحيث أي تغيير يطرأ على a سيؤثر بb، وأي تغيير يطرأ على b سيؤثر بa. اذا من المهم جدا أن نتذكر بأن الStructures من نوع القيمة (Value type)، بينما الClasses من نوع المرجع (Reference type). اختلاف آخر صغير بين الستركتشرز والكلاسات، أن الproperties في الستركتشر لا يمكن تعديلها بطريقة مباشرة من الميثودز، بل يجب استعمال كلمة mutator لكل ميثود كي نستطيع تعديل الproperties. مثال: struct Circle { var centerX = 0.0, centerY = 0.0, radius = 1.0 mutating func doubleRadius() { radius = radius * 2 } } اذا أردنا مضاعفة قيمة الradius من داخل الفنكشن doubleRadius، فسنضطر لاستخدام كلمة mutator قبل الميثود، دلالة على تغيير المتغير radius بقيمة أخرى دون الحاجة لنسخه. فيما عدا ذلك، فإن الستركتشرز تعتبر مشابهة تماما للكلاسات. ثانيا: Enumerations او enum التعدادات (Enumerations) هي طريقة نستطيع من خلالها أن نجمع العديد من قيم المتغيرات المرتبطة ببعضها. وكما الستركتشرز، فان التعدادات تعتبر من انواع القيمة (Value type). لنفترض بأننا نريد أن نعرف مجموعة الكواكب الشمسية، بدون استخدام التعدادات سنقوم بكتابة كود مشابه للتالي: let mercury = 1 let venus = 2 let earth = 3 ... وبهذه الحالة سنضطر لاضاعة أسطر أخرى للتأكد من الادخال الصحيح، فمثلا لو أدخل احدهم الرقم -1: var currentPlanet = -1 // not a valid planet! فسيكون هناك خطأ أنتاء عمل البرنامج، ان لم نقم بكتابة if-statements مناسبة ولكن في حالة التعدادات، يمكننا كتابتها كالتالي: enum Planet { case mercury = 1 case venus = 2 case earth = 3 case mars = 4 case jupiter = 5 case saturn = 6 case uranus = 7 } او اختصارا: enum Planet { case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune } والآن، ان تم ادخال قيمة غير صحيحة: var currentPlanet = Planet.mercury currentPlanet = -1 // error! فسنتعرف على الخطأ مباشرة. في هذا المثال سنرى امكانية تخزين قيم مختلفة لكل case لاحقا، الآن لننشئ مجموعة الألوان الخاصة بنا: enum Color { case rgb(Int, Int, Int) case argb(Int, Int, Int, Int) case cmyk(Int, Int, Int, Int) case name(String) } عند كتابة الenum بهذه الطريقة، فكأننا نخبر الSwift بأن كل case ستحصل على قيم خاصة بها لاحقا، مثل: var blue = Color.rgb(0, 0, 255) ويمكن استعمال الاختصار التالي عند تغيير قيمة المتغير: var blue = Color.rgb(0, 0, 255) blue = .argb(100, 0, 0, 255) blue = .name("blue") فبعد المساواة الأولى، أصبح من المعروف أن المتغير blue لن يخرج عن أحد خيارات المتعدد Color. وهنا نصل الى ختام موضوعنا، تقبل الله منا ومنكم صالح الأعمال والسلام عليكم ورحمة الله تم ترقية هذا الطرح المميز الى صفحة المقالات
  12. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته، سنتحدث في هذا الموضوع عن مفهوم الAbstract عامة وبالتحديد في لغة الJava، وكيفية استخدامه وتطبيقه مع امثلة توضيحية ماهو الAbstraction؟ اذا بحثنا في القاموس عن معنى كلمة Abstract (تجريد)، فسنجد انها تعني [ خاصية التعامل مع الفكرة لا الحدث ]. بمعنى اهمال التفاصيل الغير لازمة واستبدالها بما هو مهم وواضح. مثال على ذلك: عندما تحاول ان ترسل ايميل الى شخص ما، فانك لن تهتم بالتفاصيل الصغيرة مثل مالذي يحدث بالضبط عندما تضغط على زر ارسال او البروتوكول المستخدم لنقل الرسالة. كل ما تريد عمله هو ان تكتب عنوان الرسالة والمحتوى ومستقبل الرسالة وترسلها. نفس الشيء ينطبق في مفاهيم ال Object-Oriented. في الabstraction نهدف الى اخفاء تفاصيل الimplementation عن المستخدم، بمعنى اخر، المستخدم سيهتم بما الغرض من الobject بدلا عن كيفية قيامه به. في الجافا، يمكننا تطبيق هذا المفهوم عن طريق انشاء abstract class او abstract interface، (عكسها concrete class او normal class) Abstract Classes الكلاس الذي يحتوي على كلمة abstract في تعريفه يعتبر abstract class، وسيتبع القوانين التالية: من الممكن للAbstract class أن يحتوي على abstract methods (ليس اجباريا)، وهي الميثودز التي لا تحتوي على تعريف مثل ( ;()public abstract void get ) ولكن، اذا احتوى الكلاس على abstract method، فيجب تعريفه ك abstract class اذا تم تعريف الكلاس ك abstract، فلا يمكن انشاء objects منه لتستخدم ال abstract class وخصائصه، يجب عليك ان ترثه (inherit it) من كلاس آخر، ويجب عليك اعادة تعريف كل ال abstract methods مثال: سننشئ abstract class باضافة الكلمة abstract الى تعريف الكلاس: public abstract class Employee { private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public double computePay() { System.out.println("Inside Employee computePay"); return 0.0; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address); } public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; } } لاحظ ان الabstract class السابق لا يختلف ابدا عن الكلاس العادي، فهو يحتوي على attributes, constructor, normal methods. الفرق الوحيد هو كلمة abstract بالتعريف الآن لنحاول انشاء اوبجكت من الكلاس السابق: public class AbstractDemo { public static void main(String [] args) { Employee e = new Employee("George W.", "Houston, TX", 43); e.computePay(); } } عند تشغيل البرنامج سنحصل على الخطأ التالي: Employee.java:46: Employee is abstract; cannot be instantiated Employee e = new Employee("George W.", "Houston, TX", 43); ^ 1 error لأنه لا يمكن انشاء اوبجكت من abstract class حتى وان احتوى على constructor. Inheriting Abstract Classes نستطيع اعادة استخدام خصائص وميثودز الabstract class تماما كأي كلاس آخر عن طريق وراثته (extends): public class Salary extends Employee { private double salary; // Annual salary public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } } هنا لا يمكننا انشاء اوبجكت من كلاس Employee، ولكن يمكننا انشاء اوبجكت من كلاس Salary واستخدام جميع خصائص وميثودز كلاس Employee: public class AbstractDemo { public static void main(String [] args) { Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00); Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); System.out.println("Call mailCheck using Salary reference --"); s.mailCheck(); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); } } والOutput سيكون كالتالي: Constructing an Employee Constructing an Employee Call mailCheck using Salary reference -- Within mailCheck of Salary class Mailing check to Mohd Mohtashim with salary 3600.0 Call mailCheck using Employee reference-- Within mailCheck of Salary class Mailing check to John Adams with salary 2400.0 Abstract Methods اذا اردت انشاء ميثود ولكنك تريد تعريفها بالكلاس الإبن (Inheriting class)، يمكنك استخدام كلمة abstract في تعريف الميثود، مثال: public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); } تعريف الميثود (مثل ()computePay) ك abstract method له آثار يجب الانتباه لها: الكلاس الذي يحتويها يجب أن يكون abstract الكلاس الذي يرث الكلاس الذي يحتويها يجب أن يعيد تعريفها مثال، كلاس Salary سيرث كلاس Employee السابق: public class Salary extends Employee { private double salary; // Annual salary public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } } نلاحظ أن الميثود ()computePay تمت اعادة تعريفها لتحصل على implementation جديد خاص بكلاس Salary هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.
  13. بسم الله الرحمن الرحيم السلام عليكم ورحمة الله وبركاته، سنتحدث في هذا الموضوع عن مفهوم الAbstract عامة وبالتحديد في لغة الJava، وكيفية استخدامه وتطبيقه مع امثلة توضيحية ماهو الAbstraction؟ اذا بحثنا في القاموس عن معنى كلمة Abstract (تجريد)، فسنجد انها تعني [ خاصية التعامل مع الفكرة لا الحدث ]. بمعنى اهمال التفاصيل الغير لازمة واستبدالها بما هو مهم وواضح. مثال على ذلك: عندما تحاول ان ترسل ايميل الى شخص ما، فانك لن تهتم بالتفاصيل الصغيرة مثل مالذي يحدث بالضبط عندما تضغط على زر ارسال او البروتوكول المستخدم لنقل الرسالة. كل ما تريد عمله هو ان تكتب عنوان الرسالة والمحتوى ومستقبل الرسالة وترسلها. نفس الشيء ينطبق في مفاهيم ال Object-Oriented. في الabstraction نهدف الى اخفاء تفاصيل الimplementation عن المستخدم، بمعنى اخر، المستخدم سيهتم بما الغرض من الobject بدلا عن كيفية قيامه به. في الجافا، يمكننا تطبيق هذا المفهوم عن طريق انشاء abstract class او abstract interface، (عكسها concrete class او normal class) Abstract Classes الكلاس الذي يحتوي على كلمة abstract في تعريفه يعتبر abstract class، وسيتبع القوانين التالية: من الممكن للAbstract class أن يحتوي على abstract methods (ليس اجباريا)، وهي الميثودز التي لا تحتوي على تعريف مثل ( ;()public abstract void get ) ولكن، اذا احتوى الكلاس على abstract method، فيجب تعريفه ك abstract class اذا تم تعريف الكلاس ك abstract، فلا يمكن انشاء objects منه لتستخدم ال abstract class وخصائصه، يجب عليك ان ترثه (inherit it) من كلاس آخر، ويجب عليك اعادة تعريف كل ال abstract methods مثال: سننشئ abstract class باضافة الكلمة abstract الى تعريف الكلاس: public abstract class Employee { private String name; private String address; private int number; public Employee(String name, String address, int number) { System.out.println("Constructing an Employee"); this.name = name; this.address = address; this.number = number; } public double computePay() { System.out.println("Inside Employee computePay"); return 0.0; } public void mailCheck() { System.out.println("Mailing a check to " + this.name + " " + this.address); } public String toString() { return name + " " + address + " " + number; } public String getName() { return name; } public String getAddress() { return address; } public void setAddress(String newAddress) { address = newAddress; } public int getNumber() { return number; } } لاحظ ان الabstract class السابق لا يختلف ابدا عن الكلاس العادي، فهو يحتوي على attributes, constructor, normal methods. الفرق الوحيد هو كلمة abstract بالتعريف الآن لنحاول انشاء اوبجكت من الكلاس السابق: public class AbstractDemo { public static void main(String [] args) { Employee e = new Employee("George W.", "Houston, TX", 43); e.computePay(); } } عند تشغيل البرنامج سنحصل على الخطأ التالي: Employee.java:46: Employee is abstract; cannot be instantiated Employee e = new Employee("George W.", "Houston, TX", 43); ^ 1 error لأنه لا يمكن انشاء اوبجكت من abstract class حتى وان احتوى على constructor. Inheriting Abstract Classes نستطيع اعادة استخدام خصائص وميثودز الabstract class تماما كأي كلاس آخر عن طريق وراثته (extends): public class Salary extends Employee { private double salary; // Annual salary public Salary(String name, String address, int number, double salary) { super(name, address, number); setSalary(salary); } public void mailCheck() { System.out.println("Within mailCheck of Salary class "); System.out.println("Mailing check to " + getName() + " with salary " + salary); } public double getSalary() { return salary; } public void setSalary(double newSalary) { if(newSalary >= 0.0) { salary = newSalary; } } public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } } هنا لا يمكننا انشاء اوبجكت من كلاس Employee، ولكن يمكننا انشاء اوبجكت من كلاس Salary واستخدام جميع خصائص وميثودز كلاس Employee: public class AbstractDemo { public static void main(String [] args) { Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00); Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00); System.out.println("Call mailCheck using Salary reference --"); s.mailCheck(); System.out.println("\n Call mailCheck using Employee reference--"); e.mailCheck(); } } والOutput سيكون كالتالي: Constructing an Employee Constructing an Employee Call mailCheck using Salary reference -- Within mailCheck of Salary class Mailing check to Mohd Mohtashim with salary 3600.0 Call mailCheck using Employee reference-- Within mailCheck of Salary class Mailing check to John Adams with salary 2400.0 Abstract Methods اذا اردت انشاء ميثود ولكنك تريد تعريفها بالكلاس الإبن (Inheriting class)، يمكنك استخدام كلمة abstract في تعريف الميثود، مثال: public abstract class Employee { private String name; private String address; private int number; public abstract double computePay(); } تعريف الميثود (مثل ()computePay) ك abstract method له آثار يجب الانتباه لها: الكلاس الذي يحتويها يجب أن يكون abstract الكلاس الذي يرث الكلاس الذي يحتويها يجب أن يعيد تعريفها مثال، كلاس Salary سيرث كلاس Employee السابق: public class Salary extends Employee { private double salary; // Annual salary public double computePay() { System.out.println("Computing salary pay for " + getName()); return salary/52; } } نلاحظ أن الميثود ()computePay تمت اعادة تعريفها لتحصل على implementation جديد خاص بكلاس Salary هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.
  14. السلام عليكم ورحمة الله وبركاته، هذا الدرس البسيط سيشرح باذن الله مفهوم الOverloading وطريقة تطبيقه على لغة الJava ماهو الOverloading؟ هي ميزة تقدمها العديد من لغات البرمجة، تتيح للمبرمج كتابة اثنين او اكثر من الmethods المتكررة (تحمل نفس الاسم) ولكن تختلف بخصائصها. كيف نفرق بين هذه الmethods المتشابهة؟ صحيح ان الOverloaded methods تتشابه في الاسم، ولكنها يجب أن تختلف في أحد أو كل ما يلي: عدد الParameters نوع الParameters ترتيب الParameters أمثلة للMethod overloading: كما ذكرنا بالأعلى، فإن الOverloaded methods يجب ان تختلف في الArgument list وسنرى الآن مثال لكل حالة ممكنة للOverloading. مثال 1: اختلاف عدد الParameters class DisplayOverloading { public void disp(char c) { System.out.println(c); } public void disp(char c, int num) { System.out.println(c + " "+num); } } class Sample { public static void main(String args[]) { DisplayOverloading obj = new DisplayOverloading(); obj.disp('a'); obj.disp('a',10); } } Output: a a 10 في المثال السابق، قمنا بكتابة الميثود ()disp مرتين، مرة باستخدام Parameter واحد ومرة باستخدام اثنين. نلاحظ ان الcompiler ذكي كفاية ليربط لنا كل استدعاء بالميثود المناسبة له حسب الArgument list المستخدمة. مثال 2: اختلاف نوع الParameters class DisplayOverloading2 { public void disp(char c) { System.out.println(c); } public void disp(int c) { System.out.println(c ); } } class Sample2 { public static void main(String args[]) { DisplayOverloading2 obj = new DisplayOverloading2(); obj.disp('a'); obj.disp(5); } } Output: a 5 كما المثال السابق، نلاحظ هنا ان الميثود ()disp كتبت مرتين، مرة مع Parameter من نوع char ومرة من نوع int. مثال 3: اختلاف ترتيب الParameters في هذا المثال، قمنا بتغيير ترتيب الParameters لكتابة اكثر من نسخة من الميثود ()disp، في المرة الأولى كانت تحتوي على (char, int) وفي الثانية اصبحت (int, char). class DisplayOverloading3 { public void disp(char c, int num) { System.out.println("I’m the first definition of method disp"); } public void disp(int num, char c) { System.out.println("I’m the second definition of method disp" ); } } class Sample3 { public static void main(String args[]) { DisplayOverloading3 obj = new DisplayOverloading3(); obj.disp('x', 51 ); obj.disp(52, 'y'); } } Output: I’m the first definition of method disp I’m the second definition of method disp لنرى امثلة على طرق overload خاطئة: الحالة 1: int mymethod(int a, int b, float c) int mymethod(int var1, int var2, float var3) النتيجة: خطأ في الCompilation، كلا الميثودين يحملان نفس عدد ونوع وترتيب الParameters. الحالة 2: int mymethod(int a, int b) float mymethod(int var1, int var2) النتيجة: خطأ في الCompilation، اختلاف الreturn type للميثودين لا يهم في الoverloading. هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.
  15. السلام عليكم ورحمة الله وبركاته، هذا الدرس البسيط سيشرح باذن الله مفهوم الOverloading وطريقة تطبيقه على لغة الJava ماهو الOverloading؟ هي ميزة تقدمها العديد من لغات البرمجة، تتيح للمبرمج كتابة اثنين او اكثر من الmethods المتكررة (تحمل نفس الاسم) ولكن تختلف بخصائصها. كيف نفرق بين هذه الmethods المتشابهة؟ صحيح ان الOverloaded methods تتشابه في الاسم، ولكنها يجب أن تختلف في أحد أو كل ما يلي: عدد الParameters نوع الParameters ترتيب الParameters أمثلة للMethod overloading: كما ذكرنا بالأعلى، فإن الOverloaded methods يجب ان تختلف في الArgument list وسنرى الآن مثال لكل حالة ممكنة للOverloading. مثال 1: اختلاف عدد الParameters class DisplayOverloading { public void disp(char c) { System.out.println(c); } public void disp(char c, int num) { System.out.println(c + " "+num); } } class Sample { public static void main(String args[]) { DisplayOverloading obj = new DisplayOverloading(); obj.disp('a'); obj.disp('a',10); } } Output: a a 10 في المثال السابق، قمنا بكتابة الميثود ()disp مرتين، مرة باستخدام Parameter واحد ومرة باستخدام اثنين. نلاحظ ان الcompiler ذكي كفاية ليربط لنا كل استدعاء بالميثود المناسبة له حسب الArgument list المستخدمة. مثال 2: اختلاف نوع الParameters class DisplayOverloading2 { public void disp(char c) { System.out.println(c); } public void disp(int c) { System.out.println(c ); } } class Sample2 { public static void main(String args[]) { DisplayOverloading2 obj = new DisplayOverloading2(); obj.disp('a'); obj.disp(5); } } Output: a 5 كما المثال السابق، نلاحظ هنا ان الميثود ()disp كتبت مرتين، مرة مع Parameter من نوع char ومرة من نوع int. مثال 3: اختلاف ترتيب الParameters في هذا المثال، قمنا بتغيير ترتيب الParameters لكتابة اكثر من نسخة من الميثود ()disp، في المرة الأولى كانت تحتوي على (char, int) وفي الثانية اصبحت (int, char). class DisplayOverloading3 { public void disp(char c, int num) { System.out.println("I’m the first definition of method disp"); } public void disp(int num, char c) { System.out.println("I’m the second definition of method disp" ); } } class Sample3 { public static void main(String args[]) { DisplayOverloading3 obj = new DisplayOverloading3(); obj.disp('x', 51 ); obj.disp(52, 'y'); } } Output: I’m the first definition of method disp I’m the second definition of method disp لنرى امثلة على طرق overload خاطئة: الحالة 1: int mymethod(int a, int b, float c) int mymethod(int var1, int var2, float var3) النتيجة: خطأ في الCompilation، كلا الميثودين يحملان نفس عدد ونوع وترتيب الParameters. الحالة 2: int mymethod(int a, int b) float mymethod(int var1, int var2) النتيجة: خطأ في الCompilation، اختلاف الreturn type للميثودين لا يهم في الoverloading. هنا نصل الى نهاية موضوعنا، أتمنى لي ولكم التوفيق والسداد.

عالم البرمجة

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