سويفت 5.1 - ما الجديد؟



أصبح Swift 5.0 متاحًا مع إصدار Xcode 10.2 ، لكن العمل على الإصدار التالي مستمر وهناك بالفعل أخبار عما يمكنك توقعه فيه.

تتمثل الميزة الرئيسية لـ Swift 5.1 في استقرار الوحدة ، مما يسمح لنا باستخدام مكتبات الطرف الثالث دون القلق بشأن إصدار برنامج التحويل البرمجي Swift الذي تم إنشاؤه باستخدامه. يشبه استقرار ABI الذي حصلنا عليه في Swift 5.0 ، ولكن هناك اختلاف بسيط: يحل استقرار ABI الاختلافات في إصدارات Swift في وقت التشغيل ، واستقرار الوحدة في وقت الترجمة.

بالإضافة إلى هذا الابتكار المهم ، سنتلقى العديد من التحسينات المهمة في Swift ، وفي هذه المقالة سنتعرف عليها بأمثلة حتى تتمكن من رؤيتها في العمل.

النفس العالمي


يمتد SE-0068 إلى استخدام Self ، بحيث يشير إلى النوع الذي يحتوي عليه داخل الفئات والبنى والتعدادات. هذا مفيد عادة للأنواع الديناميكية عندما يكون من الضروري تحديد النوع الدقيق لشيء ما في وقت التشغيل.

كمثال ، خذ بعين الاعتبار الكود التالي:

class NetworkManager { class var maximumActiveRequests: Int { return 4 } func printDebugData() { print("Maximum network requests: \(NetworkManager.maximumActiveRequests).") } } 

نحن هنا تحديد خاصية ثابت الأقصىActiveRequests داخل فئة NetworkManager وإضافة الأسلوب printDebugData () لطباعة هذه الخاصية. كل شيء على ما يرام هنا ، ولكن فقط حتى نقرر أن نرث من NetworkManager :

 class ThrottledNetworkManager: NetworkManager { override class var maximumActiveRequests: Int { return 1 } } 

في هذا الوريث ، نقوم بتغيير خاصية maxActiveRequests بحيث تصبح الآن مساوية لواحد ، ولكن إذا قمنا باستدعاء printDebugData () ، فسوف نستنتج القيمة من الفئة الأصل:

 let manager = ThrottledNetworkManager() manager.printDebugData() 

هنا يجب أن نحصل على 1 بدلاً من 4 ، ومن هنا يأتي الإنقاذ SE-0068: يمكننا استخدام Self (مع رأس المال 'S') للإشارة إلى النوع الحالي. حتى الآن يمكننا إعادة كتابة أسلوب printDebugData () للفئة الأم مثل هذا:

 class ImprovedNetworkManager { class var maximumActiveRequests: Int { return 4 } func printDebugData() { print("Maximum network requests: \(Self.maximumActiveRequests).") } } 

هذا يعني أن Self تعمل بنفس الطريقة التي عملت بها في البروتوكولات في الإصدارات السابقة من Swift.

تحذيرات من الغموض لا شيء


يتم تطبيق الاختيارات في Swift كتعداد مع خيارين: البعض و لا شيء . يمكن أن يؤدي هذا إلى حدوث ارتباك إذا أنشأنا تعدادًا خاصًا به خيارًا بلا شيء ولفه بشكل اختياري . على سبيل المثال:

 enum BorderStyle { case none case solid(thickness: Int) } 

عند استخدام كل شيء غير اختياري ، يكون نظيفًا:

 let border1: BorderStyle = .none print(border1) 

هذا سوف يخرج "لا شيء". ولكن إذا استخدمنا هذا التعداد اختياريًا ، فسنواجه مشكلة:

 let border2: BorderStyle? = .none print(border2) 

ستتم طباعة Nil هنا ، حيث يعتقد Swift أن .none يعني اختياريًا فارغًا ، على الرغم من أنه اختياري بالفعل بقيمة BorderStyle.none.
في Swift 5.1 ، في حالة هذا الغموض ، سيتم عرض تحذير:
"على افتراض أنك تعني" اختياري "بلا" ؛ هل تقصد "BorderStyle.none" بدلاً من ذلك؟ "
وبالتالي ، سيتم إعلام المطور أنه مع الكود الخاص به ، لن يكون كل شيء سلسًا.

مطابقة التعدادات الاختيارية وغير الاختيارية


Swift ذكي بما فيه الكفاية لفهم بنية التبديل / الحالة عند الجمع بين القيم الاختيارية / غير الصحيحة للنصوص والقيم الصحيحة ، ولكن ليس في حالة التعدادات.

الآن في Swift 5.1 ، يمكننا استخدام مفتاح التبديل / الحالة لمطابقة خيارات التعداد الاختيارية وغير الاختيارية:

 enum BuildStatus { case starting case inProgress case complete } let status: BuildStatus? = .inProgress switch status { case .inProgress: print("Build is starting…") case .complete: print("Build is complete!") default: print("Some other build status") } 

يمكن لـ Swift تعيين تعدادات اختيارية للخيارات غير الاختيارية ، وسيتم عرض "Build is بدأ ..." هنا.

مقارنة المجموعات المطلوبة


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

المبدأ الأساسي بسيط - يوفر Swift 5.1 اختلافًا جديدًا في الطريقة (من :) ، والذي يحدد الاختلافات بين مجموعتين مرتبتين - العناصر التي يجب إضافتها وأي العناصر المراد إزالتها. ينطبق هذا على أي مجموعات مرتبة تحتوي على عناصر تتوافق مع بروتوكول Equatable .

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

ملاحظة: نظرًا لأن Swift يتم توزيعه الآن كجزء من أنظمة تشغيل Apple ، فيجب استخدام أدوات لغة جديدة مع #available للتحقق للتأكد من أن الشفرة تعمل على نظام تشغيل يدعم الوظيفة المطلوبة. بالنسبة للوظائف التي تعمل على أنظمة تشغيل غير معروفة وغير معلنة قد يتم إصدارها في المستقبل ، يتم استخدام رقم إصدار خاص هو "9999" ، مما يعني: "لا نعرف بعد رقم الإصدار الصحيح".

 var scores1 = [100, 91, 95, 98, 100] let scores2 = [100, 98, 95, 91, 100] if #available(iOS 9999, *) { let diff = scores2.difference(from: scores1) for change in diff { switch change { case .remove(let offset, _, _): scores1.remove(at: offset) case .insert(let offset, let element, _): scores1.insert(element, at: offset) } } print(scores1) } 

للحصول على رسوم متحركة أكثر تقدمًا ، يمكننا استخدام المعلمة الثالثة في قائمة الاختلافات الناتجة: المرتبطة مع . وبالتالي ، بدلاً من .insert (ترك الإزاحة ، اترك العنصر ، _) ، يمكننا كتابة. إدراج (السماح للإزاحة ، السماح للعنصر ، السماح بالإرفاق). هذا يعطينا القدرة على تتبع أزواج من التغييرات في وقت واحد: تحريك العنصر في المجموعة موضعين إلى أسفل هو حذف العنصر ثم إضافته ، وربطه "بربط" هذين التغييرين معًا ويسمح لك بمراعاة هذه الحركة.

بدلاً من تطبيق الاختلافات يدويًا ، واحدة تلو الأخرى ، يمكنك تطبيقها في ضربة واحدة باستخدام طريقة application () الجديدة:

 if #available(iOS 9999, *) { let diff = scores2.difference(from: scores1) let result = scores1.applying(diff) ?? [] } 

إنشاء صفائف غير مهيأة


قدم SE-0245 مُهيئًا جديدًا للصفائف التي لا تملأ بالقيم الافتراضية. كانت متاحة في وقت سابق كواجهة برمجة تطبيقات خاصة ، مما يعني أن Xcode لم يطالب بها عند إكمال التعليمات البرمجية ، ولكن يمكنك استخدامها إذا كنت في حاجة إليها وفهمت خطر أن هذه الوظيفة قد لا تكون في المستقبل.

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

على سبيل المثال ، يمكننا إنشاء مجموعة من 10 أعداد صحيحة عشوائية مثل هذا:

 let randomNumbers = Array<Int>(_unsafeUninitializedCapacity: 10) { buffer, initializedCount in for x in 0..<10 { buffer[x] = Int.random(in: 0...10) } initializedCount = 10 } 

هناك العديد من القواعد:

  1. لا تحتاج إلى استخدام وحدة التخزين بالكامل التي طلبتها ، ولكن لا يمكنك تجاوزها. أي إذا قمت بتعيين حجم الصفيف على 10 ، فيمكنك ضبط initializedCount في النطاق من 0 إلى 10 ، لكن ليس 11.
  2. إذا لم تقم بتهيئة العناصر المستخدمة في الصفيف ، على سبيل المثال ، قمت بتعيين initializedCount إلى 5 ، لكنك لم تقدم قيمًا حقيقية للعناصر من 0 إلى 4 ، فمن المرجح أن تتلقى قيمًا عشوائية. كما تعلمون ، هذا خيار سيء.
  3. إذا لم تقم بتعيين initializedCount ، فسيكون مساوياً لـ 0 وسيتم فقد جميع البيانات التي قمت بتعيينها.

نعم ، يمكننا إعادة كتابة الكود باستخدام map () :

 let randomNumbers2 = (0...9).map { _ in Int.random(in: 0...10) } 

من الواضح أن هذا أكثر قابلية للقراءة ، ولكنه ليس فعالًا: فنحن ننشئ نطاقًا ، ثم صفيفًا فارغًا جديدًا ، ونخصص له حجمًا ، و "نمر" في النطاق بأكمله ، مع تطبيق إغلاق لكل عنصر.

استنتاج


لا يزال قيد Swift 5.1 ، وعلى الرغم من مرور الفرع الأخير لـ Swift نفسه ، فإن التغييرات من بعض المشاريع الأخرى ذات الصلة لا تزال مرئية.

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

نقطة أخرى تستحق الاهتمام. لم يكن هناك نتيجة لتطور سويفت اثنين من التغييرات على هذه القائمة ("التحذيرات في حالة غموض خيار لا شيء" و "مطابقة التعدادات الاختيارية وغير الاختيارية").

Source: https://habr.com/ru/post/ar446522/


All Articles