مرحبا اسمي ايليا. أنا مطور دائرة الرقابة الداخلية في Tinkoff.ru. في هذه المقالة ، سأقدم نظرة عامة مختصرة على التغييرات الرئيسية في Swift 5. هذه التغييرات موصوفة في 
ملاحظات الإصدار . بالنسبة لأولئك الذين لم تتعرف على نفسك بعد ، مرحبًا بكم في cat!

سوف ينخفض حجم التطبيق!
لن تتضمن التطبيقات المكتوبة بلغة Swift 5 والتي تم تجميعها لنظام التشغيل iOS 12.2 و watchOS 5.2 و tvOS 12.2 مكتبات ديناميكية لمكتبة Swift القياسية و Swift SDK. وهذا يعني أن حجم التطبيق سينخفض ، ولكن ليس كثيرًا. إذا كنت تعتقد أن 
هذه التغريدة ، فقد تم تقليل حجم المشروع الفارغ من 2.4 ميغابايت إلى 24 كيلوبايت. نتيجة جيدة للتطبيقات الصغيرة ، ولكن بالنسبة للتطبيقات الكبيرة لن يكون هناك فرق كبير.
dynamicCallable ( SE-0216 )
تسمح 
لك السمة 
dynamicCallable بالعمل مع كائن كدالة. تسمى هذه الكائنات كائنات وظيفية أو عوامل توجيه (يمكن العثور على مزيد من التفاصيل 
هنا ). الكائنات الوظيفية هي في لغة C ++ و Python و JavaScript ولغات أخرى ، وفي لغة سويفت تمت إضافتها للتوافق مع هذه اللغات. الحقيقة هي أن Swift يتفاعل الآن بشكل جيد مع API C و Objective-C ، ويريد مطورو اللغة إضافة التفاعل مع اللغات الديناميكية - Python و JavaScript و Ruby وغيرها.
من أجل جعل الكتابة مُشغّلاً ، يجب إضافة السمة 
@ dynamicCallable إلى الإعلان الخاص بها. النظر في مثال على هيكل 
المخفض الذي يمكن استخدامه لإضافة أرقام في صفيف:
@dynamicCallable struct Reducer { ... } 
ثم تحتاج إلى تنفيذ أحد الأساليب التالية أو كليهما:
 func dynamicallyCall(withArguments: ExpressibleByArrayLiteral) func dynamicallyCall(withKeywordArguments: ExpressibleByDictionaryLiteral) 
تتيح لك الوظيفة الأولى الوصول إلى الكائن عن طريق تمرير صفيف كوسائط. تتيح لك الوظيفة الثانية الوصول إلى الكائن ، بتمرير نفس الصفيف مثل الوسائط ، ولكن باستخدام أسماء الوسائط.
على سبيل المثال ، يبدو تنفيذ الوظيفة الأولى لهيكل 
المخفض كما يلي:
 func dynamicallyCall(withArguments arguments: [Int]) -> Int { return arguments.reduce(0, +) } 
ثم تطبيق مثل هذا الهيكل على النحو التالي:
 let reducer = Reducer() let sum = reducer(1, 2, 3)  
سننظر في تنفيذ الطريقة الثانية باستخدام مثال بنية 
المقارنة ، والذي يمكننا من خلاله مقارنة رقمين:
 @dynamicCallable struct Comparator { func dynamicallyCall(withKeywordArguments arguments: KeValuePairs<String, Int>) -> ComparisonResult { guard let lhs = arguments["lhs"], let rhs = arguments["rhs"], lhs != rhs else { return .orderedSame } return lhs > rhs ? .orderedDescending : .orderedAscending } } 
يمكنك استخدام هذا الهيكل على النحو التالي:
 let comparator = Comparator() let comparisionResult = comparator(lhs: 1, rhs: 2)  
يعلم الكثير من الناس أنه عند معالجة قيم التعداد ، من الضروري وصف جميع الحالات ومحاولة عدم استخدام الإعداد الافتراضي. على الرغم من أن هذا المطلب يضيف القليل من الأمان ، إلا أنه يحتوي أيضًا على عيب ، لأنه عند تغيير القيم في التعداد ، تحتاج إلى إضافة معالجتها. لا تزال هناك فرصة لتغيير إطار النظام بعض التعدادات ، لكن لم تتم معالجة ذلك في التطبيق الخاص بك (لذلك ، على سبيل المثال ، كان مع 
LABiometryType ).
سيضيف Swift 5 السمة 
غير المعروفة ، مما سيتيح لك فصل سيناريوهين مختلفين عند معالجة التعداد:
- يجب تنفيذ التعليمات البرمجية الافتراضية في جميع الحالات التي لم تتم معالجتها بتبديل
- تتم معالجة جميع الحالات في التبديل ، وإذا تمت إضافة حالات جديدة ، فأنت بحاجة إلى استخدام الرمز بشكل افتراضي
لنلقِ نظرة على مثال:
 enum HTTPMethod { case post, get, put }  
التخلص من ضعف اختياري نتيجة لاستدعاء وظيفة مع محاولة؟ ( SE-0230 )
بالتأكيد صادف الكثيرون حقيقة أنه عند استدعاء وظيفة رمي ، والتي تعود 
اختياري ، باستخدام 
محاولة؟ ، والنتيجة هي نوع ملفوف في اثنين 
اختياري . هذه ليست مريحة للغاية ، وحتى في سويفت 5 ، اتصل 
محاولة؟ في هذه الحالة سيعود نوع ملفوف في واحد 
اختياري فقط.
هكذا كان الحال قبل Swift 5:
 let result = try? optionalObject?.foo()  
وهكذا سيكون في Swift 5:
 let result = try? optionalObject?.foo()  
تحقق التعددية ( SE-0225 )
للتحقق من تعدد رقم لآخر ، يمكنك استخدام 
isMultiple (of :) ، بدلاً من باقي القسمة (٪):
 
التغيير بسيط ، لكنه يجعل الكود أكثر وضوحًا ويبسط عملية البحث عن طريق الكود.
حساب عدد العناصر في تسلسل مع شرط ( SE-0220 )
في Swift 5 ، سيضيف نوع التسلسل 
العد (حيث: (العنصر) -> Bool) -> طريقة ، والتي سوف تتيح لك حساب عدد العناصر في تسلسل تفي بشرط معين في مرور واحد. قبل ذلك ، اضطررت إلى استخدام 
مرشح بالتزامن مع 
العد . ستوفر هذه الطريقة الذاكرة المخصصة عند إنشاء صفيف جديد في طريقة 
التصفية .
مثال:
 let countOfZeroes = [0, 1, 2, 0, 4].count(where: { $0 == 0 })  
طريقة CompactMapValues في القاموس ( SE-0218 )
هذه الطريقة تجمع بين 
compMap من 
Array و 
mapValues من 
القاموس . نتيجة لاستدعاء هذه الطريقة ، يتم إنشاء قاموس ذو قيم محولة لا توجد فيه قيم تساوي 
الصفر .
مثال:
 let dictionary = ["a": "1", "b": "2", "c": "Number"] let resultDictionary = dictionary.compactMapValues { Int($0) }  
أضيفت القدرة على كتابة السطور التي تستخدم فيها علامات الاقتباس و الشرطة المائلة للخلف كأحرف عادية ، وليس كأحرف خاصة. للقيام بذلك ، أضف الحرف # في بداية ونهاية السطر.
مثال:
 let string1 = #"   " ""# let string2 = #"  \ "# 
إذا كنت تقوم بإدخال متغير عند إنشاء خط ، فأنت بحاجة إلى إضافة علامة # بعد:
 let string = #"   \#(variable)"# 
إذا كان للخط علامة # ، فأنت بحاجة إلى إضافة علامتي ## في بداية ونهاية السطر:
 let string = ##"   #"## 
بروتوكول التسلسل لم يعد يحتوي على النوع المقترن SubSequence ( SE-0234 )
تم نقل النوع 
الترابطي من 
SubSequence من بروتوكول 
Sequence إلى 
Collection ، والآن ترجع جميع الأساليب في 
Sequence التي أعادت 
SubSequence نوعًا معينًا. على سبيل المثال ، تقوم الطريقة 
اللاحقة الآن بإرجاع 
صفيف . فيما يلي قائمة كاملة بالطرق التي تأثرت بهذا التغيير:
 extension Sequence { public func dropFirst(_ k: Int = 1) -> DropFirstSequence<Self> public func dropLast(_ k: Int = 1) -> [Element] public func suffix(_ maxLength: Int) -> [Element] public func prefix(_ maxLength: Int) -> PrefixSequence<Self> public func drop(while predicate: (Element) throws -> Bool) rethrows -> DropWhileSequence<Self> public func prefix(while predicate: (Element) throws -> Bool) rethrows -> [Element] public func split( maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true, whereSeparator isSeparator: (Element) throws -> Bool ) rethrows -> [ArraySlice<Element>] } 
الآن العمل مع هذه الأساليب سوف تصبح أسهل.
قيود البروتوكول
تدعم البروتوكولات الآن التقييد في شكل فئات تنفذ هذا البروتوكول. بمعنى آخر ، يمكنك الآن الإشارة إلى أنه لا يمكن تنفيذ البروتوكول إلا من خلال فئة معينة. على سبيل المثال:
 protocol Viewable: UIView {} protocol Viewable where Self: UIView {} 
يتم دعم خيار التسجيل الثاني في Swift 4.2 ، ولكنه قد يتسبب في حدوث خطأ في الترجمة أو وقت التشغيل. في Swift 5 ، لن يحدث هذا الخطأ.
الخاتمة
هذه ليست قائمة كاملة بالتغييرات في Swift 5 ؛ حيث يتم جمع التغييرات الرئيسية فقط هنا. بشكل عام ، تكون التغييرات المقدمة إيجابية وتجعل اللغة أكثر قابلية للفهم ومرونة. الشيء الرئيسي هو أن "تحويل إلى صيغة سويفت الحالية" يجب أن تكون غير مؤلمة.
هذا كل شيء ، شكرا للقراءة.