مساحة اعلانية

آخر المواضيع

تعلم Swift من الصفر: الاختيارات والتحكم بالتدفق

تعلم Swift من الصفر: الاختيارات و التحكم بالتدفق
تعلم Swift من الصفر: الاختيارات و التحكم بالتدفق

في الدروس السابقة، تعلمت بعض المفاهيم الأساسية في لغة البرمجة Swift. إذا قمت بالبرمجة من قبل، فأنا واثق بأنك رأيت بعض نقاط التشابه مع لغات البرمجة الأخرى، مثل JavaScript ،Ruby و Objective-C. 
في هذا الدرس، سنركز على التحكم بالتدفق في Swift. قبل أن نناقش التحكم بالتدفق بعمق أكثر، نحتاج إلى أن نلقي نظرة على مفهوم يعتبر جديداً لمعظمكم، الاختيارات. تعد الاختيارات ميزة من ميزات الأمان لدى Swift. في بادئ الأمر، يمكن أن يشكل استخدام الاختيارات عائقاً، ولكنك سوف تتعلم بسرعة أن الاختيارات ستجعل الكود آمن بكثير.

1. الاختيارات
لقد رأينا مسبقاً أنه يجب بدء المتغير قبل استخدامه. ألق نظرة على المثال التالي لتفهم بشكل أفضل ما الذي يعنيه ذلك.   

var str: String

str.isEmpty


في حال كنت متعاداً على العمل مع النصوص في Objective-C، فيمكن أن تتفاجأ أن Swift أظهر لك أن هنالك خطأ. دعونا نرى ما الذي يخبرنا به هذا الخطأ.

في عدة لغات، لدى المتغيرات قيمة افتراضية أولية. في Objective-C، على سبيل المثال، فإن النص في المقطع التالي يساوي الصفر.
   
NSString *newString;


ومع ذلك، فإن مفهوم الصفر يختلف في Swift و Objective-C. سنناقش الصفر بعمق أكثر لاحقاً.

ما هو الاختياري؟
يستخدم Swift الاختيارات لاحتواء مفهوم مهم، أي متغير أو ثابت لديه قيمة أو لا. إنها بهذه البساطة في Swift. من أجل إعلان متغير أو ثابت كاختياري، سنضيف إشارة استفهام لنوع المتغير أو الثابت.
   
var str: String?

لم يعد المتغير str من نوع String. أنه الآن من نوع optional String. من الضروري فهم ذلك. ناتج ذلك أو أثره الجانبي هو أننا لم نعد قادرين على التفاعل مباشرة مع قيمة المتغير str. تخزن القيمة بشكل آمن في الاختياري ونحتاج إلى سؤال الاختياري عن القيمة التي يحتويها.

الإزالة الإجبارية
إحدى طرق الولوج إلى قيمة اختيارية هي الإزالة الإجبارية. يمكننا الولوج إلى قيمة المتغير srt من خلال إضافة an ! لاسم المتغير.   
var str: String?

str = "Test"

println(str!)


من الضروري أن تحرص على أن الاختياري يحوي على قيمة عندما تفرض الإزالة. في حال لم يحوي الاختياري على قيمة وقمت بإجباره على الإزالة، فإن Swift سيظهر لك أن هنالك خطأ ما.

ربط الاختياري
هنا طريقة آمنة للولوج إلى قيمة اختيارية ما. سنأخذ نظرة أقرب على التصريحات خلال دقائق، ولكن المثال التالي يظهر كيف يمكننا الولوج بشكل آمن القيمة المخزنة في متغير str، الذي ينتمي إلى نوع optional String.

   
var str: String?



if str != nil {

    println(str!)

} else {

    println("str has no value")

}


سنتحقق أولاً من أن المتغير str يساوي الصفر قبل أن نطبع المحتوى. في هذا المثال، ليس لدى Str أية قيمة، والذي يعني أنه لا يمكن إجبارها على الإزالة عن طريق الصدفة.

هنالك طريقة أسهل تدعى ربط الاختياري. في المثال التالي، سنعين القيمة المخزنة في الاختياري لثابت مؤقت، والذي يستخدم في جملة. إذا تربط قيمة الاختياري str بالثابت strConst وتستخدم في جملة. إذا تعمل هذه الطريقة أيضاً في جمل بينما.
   
var str: String?

str = "Test"

if let strConst = str {

    println(strConst)

} else {

    println("str has no value")

}


ما هو الصفر؟
إذا كنت تعرف Objective-C، فحتماً تعرف ما هو الصفر. في Objective-C، يعد الصفر مؤشراً لكائن غير موجود. يعرف Swift الصفر بطريقة مختلفة قليلاً وأنه من الضروري أن تفهم هذا الاختلاف.

في Swift، يعني الصفر غياب قيمة ما، أية قيمة كانت. في حين لا يطبق الصفر إلا على الكائنات في Objective-C، فإن الصفر في Swift يمكن أن يستخدم لأي نوع. لذلك من الضروري أن تفهم أن الاختياري ليس مساوياً للصفر في Objective-C. تعد هذه المفاهيم مختلفة جداً.

2. تحكم التدفق
يقدم Swift عدداً من المفاهيم الشائعة للتحكم بتدفق الكود التي تكتبها. إذا كانت لديك أية خبرة في البرمجة، فلن يكون لديك أية مشكلة بالتعامل بسرعة مع مفاهيم التحم بالتدفق، إذا الشرطية، جمل التحول، وعقد لأن وبينما  الخاصة بـ Swift.

ومع ذلك، فإن Swift لن يكون Swift إذا لم تختلف مفاهيم التحكم بالتدفق قليلاً عن تلك الموجودة، على سبيل المثال، Objective-C's. في حين أن التفاصيل مهمة، فإنني متأكد بأنهم لن يعيقوا تعاملك السريع مع Swift. دعوني ابدأ بالمفهوم الشرطي الشائع، جملة IF.

IF
تعد جمل إذا مشابهة جداً لتلك الموجودة في Objective-C. الاختلاف الرئيسي هو أنه لا داعي للف الشرط بقوسين. ولكن الأقواس المعوجة إجبارية. يمنع اللاحق المطورين من تقديم الفيروسات الشائعة التي ترتبط بكتابة جمل إذا من دون أقواس معوجة. هذا ما ستبدو عليه جملة إذا في Swift.  
let a = 10

if a > 10 {

    println("The value of \"a\" is greater than 10.")

} else {

    println("The value of \"a\" is less than or equal to 10.")

}


لا يجب أن تتفاجأ لمعرفة أن Swift يعرف جملة أخرى أيضاً. تنفذ كود جملة أخرى في حال كان الشرط مساوياً للخطأ. من الممكن أيضاً ربط جمل إذا كما هو موضح في المثال التالي. 
let a = 10

if a > 10 {

    println("The value of \"a\" is greater than 10.")

} else if a > 5 {

    println("The value of \"a\" is greater than 5.")

} else {

    println("The value of \"a\" is less than or equal to 5.")

}

هنالك ملحوظة مهمة يجب أن أبوح بها وهي أن شرط جملة إذا يجب أن يعود بصح أو خطأ. هذا لا ينطبق على جمل إذا في Objective-C. ألق نظرة على جملة إذا التالية المكتوبة بـ Objective-C.  
NSArray *array = @[];

if (array.count) {

    NSLog(@"The array contains one or more items.");

} else {

    NSLog(@"The array is empty.");

}


في حال كنا قد حولنا مقطع الكود الذي فوق إلى Swift، فإننا كنا سنقع في الخطأ. لا يخبر هذا الخطأ بالكثير، ولكن Swift يخبرنا بالفعل أنه يجب علينا أن نتأكد أن نتيجة الشرط يقدر بصح أو خطأ.

الطريقة الصحيحة لترجمة مقطع Objective-C السابق إلى Swift هي من خلال التأكد أن شرط جملة إذا تقدر بصح أو خطأ، كما هو في المقطع التالي.
   
let array = [String]()

if array.count > 0 {

    println("The array contains one or more items.")

} else {

    println("The array is empty.")

}

التحويل
تعد جملة التحويل في Swift أقوى من نظيرتها التي في Objective-C. وهي أيضاً آمنة كما ستعرف بعد قليل. في حين أن هنالك بعض الاختلافات، جمل التحويل في Swift تلتزم بنفس المفهوم التي تتبعه باقي لغات البرمجة، تمرر قيمة إلى جملة التحويل وتتم مقارنتها بأنماط  ملائمة محتملة.

هذا صحيح، أنماط. كما قلت، فإن لدى جملة التحويل في Swift بضعة خدع مخبأة. سنلق نظرة على هذه الخدع خلال لحظات. دعونا نتحدث عن الأمان أولاً.

شاملة
يتوجب على جملة التحويل في Swift أن تكون شاملة، أي أنه يجب إعطاء كل قيمة محتملة من النوع المعطى إلى جملة التحويل إلى جملة التحويل ذاتها. كما هي الحال في Objective-C، تحل هذه المشكلة بسهولة من خلال إضافة صنف افتراضي كما يوضح المثال التالي.
let a = 10

switch a {

    case 0:

        println("a is equal to 0")

    case 1:

        println("a is equal to 1")

    default:

        println("a has another value")

}

Fallthrough


أحد أوجه الاختلاف مع Objective-C في إنشاء جمل التحويل هو نقص fallthrough الضمني. المثال التالي لا يعمل في Swift لبضعة أسباب.

   
let a = 10

switch a {

    case 0:

    case 1:

        println("a is equal to 1")

    default:

        println("a has another value")

}

في الصنف الأول حيث تمت مقارنة a مع 0 لم تنجح بشكل ضمني في الصنف الثاني حيث تمت مقارنة a مع 1. في حال أضفت المثال الذي في الأعلى لملعبك، ستلاحظ أن سيظهر لك أن هنالك خطأ ما. يقول الخطأ أنه يجب على كل صنف أن يتضمن على الأقل جملة واحدة قابلة للتنفيذ.

لاحظ أن أصناف جملة التحويل لا تتضمن جمل منفصلة لتفصل جملة التحويل. يعد هذا غير مطلوباً في Swift بما أن fallthrough الضمني غير موجود أصلاً في Swift. هذا سيقلل فرص ظهور فيروسات بسبب fallthrough غير المقصود.

الأنماط
تكمن قوة جملة التحويل في Swift في الأنماط المتطابقة. ألق نظرة على المثال التالي. لقد قمت باستخدام سلاسل لمقارنة القيم.
let a = 10

switch a {

    case 0..<5:

        println("The value of a lies between 0 and 4.")

    case 5...10:

        println("The value of a lies between 5 and 10.")

    default:

        println("The value of a is greater than 10.")

}

يعرف العامل ..< أو العامل نصف المفتوح سلسلة من القيمة الأولى للقيمة الثانية، باستثناء القيمة الثانية. يعرف العامل .. أو العامل المنغلق سلسلة من القيمة الأولى للقيمة الثانية، متضمناً القيمة الثانية. تعد هذه العوامل مفيدة جداً في عدة حالات.

يمكنك أيضاً أن تقارن قيم جملة التحويل بالحقول الفارغة (tuples). ألق نظرة على المثال التالي وانظر كيف يعمل.
let latlng = (34.15, -78.03)

switch latlng {

case (0, 0):

    println("We're at the center of the planet.")

case (0...90, _):

    println("We're in the Northern hemisphere.")

case (-90...0, _):

    println("We're in the Southern hemisphere.")

default:

    println("The coordinate is invalid.")

}

كما يمكنك أن ترى في المثال الذي في الأعلى، من الممكن أن تتطابق القيمة مع أكثر من صنف واحد. عندما يحصل ذلك، فإن أول صنف مطابق هو الذي يتم اختياره. يوضح المثال أيضاً استخدام underscore ] _ [. كما رأينا في الدرس السابق، يمكننا استخدم underscore لإخبار Swift عن القيم التي لا نهتم لأمرها.

ربط القيم
يمكن أيضاً ربط القيم مع جمل التحويل كما يوضح المثال التالي. القيمة الثانية للحقل الفارغ تربط بشكل مؤقت مع الوصف الثابت للإستخدام في الصنف الأول والثاني. 
var response = (200, "OK")

switch response {

case (200..<400, let description):

    println("The request was successful with description \(description).")

case (400..<500, let description):

    println("The request was unsuccessful with description \(description).")

default:

    println("The request was unsuccessful with no description.")

}

FOR
سنتطلع أولاً على مفهوم عقدة لأجل. إنها تتصرف بشكل مشابه جداً لعقد لأجل في اللغات الأخرى. هنالك صنفان، عقدة لأجل وعقدة for-in.

FOR
تعد عقدة لأجل مطابقة تقريباً لتلك التي في Objective-C كما يوضح المثال الآتي. تنفذ عقدة لأجل عدداً من الجمل حتى يتم تعيين شرط معرف مسبقاً.
for var i = 0; i < 10; i++ {

    println("i is equal to \(i).")

}


كما هو الحال في جمل إذا، ليس هنالك داع لاستخدام الأقواس لاحتواء تعاريف عملية بدء العقدة، الشرط والزيادة. ولكن جمل العقدة تحتاج لأن يتم احتواؤها بأقواس معوجة.

for-in
تعد عقد for-in (لأجل-في) مثالية لعقد محتويات سلسلة أو مجموعة. في المثال التالي، سنعقد العناصر في مصفوفة.
   
let numbers = [1, 2, 3, 5, 8]

for number in numbers {

    println("number is equal to \(number)")

}

يمكننا أيضاً استخدام عقد for-in من أجل عقد أزواج القيم الأساسية في القاموس. في المثال التالي، سنعلن عن قاموس وسنطبع محتواه في لوحة المراقبة. كما رأينا مسبقاً في هذه السلسلة، فإنه لا يمكن تعريف سلسلة أزواج القيم الأساسية ذلك لأن القاموس عبارة عن مجموعة من أزواج قيم أساسية غير منظمة. 
var bids = ["Tom": 100, "Bart": 150, "Susan": 120]

for (name, bid) in bids {

    println("\(name)'s bid is $\(bid).")

}


يحفظ كل زوج من القيم الأساسية في القاموس بعقدة for-in كحقل فارغ لثوابت مسماة. تعد عقدة for-in رائعة للإرتباط مع السلاسل. إنني واثق بأنك توافقني الرأي بأن المقطع الذي بالأسفل سهل القراءة والفهم ويرجع الفضل بذلك لاستخدام السلسلة المنغلقة.
for i in 1...10 {

    println("i is equal to \(i)")

}


while
تأتي العقدة أيضاً في نوعين، بينما وأفعل - بينما. أن الاختلاف الوحيد بينهما هو أن مجموعة جمل عقدة أفعل - بينما يتم تنفيذها على الأقل مرة واحدة، ذلك لأن شرط عقدة أفعل - بينما تقيم في نهاية كل تكرير. يوضح المثال التالي هذا الاختلاف.   
var c = 5

var d = 5

while c < d {

    println("c is smaller than d")

}



do {

    println("c is smaller than d")

} while c < d


لن يمكن تنفيذ جملة println التابعة لعقدة بينما ولكن تلك التابعة لعقدة do-while (أفعل - بينما) فقد تم تنفيذها مرة واحدة.

في عدة حالات، يمكن لعقد لأجل أن تعاد كتابتها كعقد بينما وهذا غالباً يعود للمطور لكي يقرر أي نوع من العقد يرغب باستخدامه في حالة معينة. في المثال التالي نرى أن نتيجة عقد لأجل وبينما هي واحدة.
for var i = 0; i < 10; i++ {

    println(i)

}



var i = 0



while i < 10 {

    println(i)

    i++

}

الخلاصة
ما زال هنالك الكثير عن التحكم بالتدفق في Swift أكثر مما قد ذكرناه في هذا الدرس، ولكن لديك الآن فهماً أساسياً لتتابع رحلتك التعليمية في Swift. أمل أن هذا الدرس قد أراك أن إنشاء التحكم بالتدفق في Swift مشابهاً جداً لما يحصل في باقي لغات البرمجة.

في باقي هذه السلسلة، ستستفيد أكثر من مفاهيم التحكم بالتدفق وستفهم بالتدريج الاختلافات الطفيفة بين Swift ولغات أخرى كـ Objective-C. في التنصيب القادم لهذه السلسلة، سنبدأ باستطلاع الدوال.

الكــاتــب

    • مشاركة

ليست هناك تعليقات:

جميع الحقوق محفوظة لــ الشبح للمعلوميات 2019 ©