ما الجديد في Swift 5؟

مرحبا اسمي ايليا. أنا مطور دائرة الرقابة الداخلية في 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) // sum = 6 

سننظر في تنفيذ الطريقة الثانية باستخدام مثال بنية المقارنة ، والذي يمكننا من خلاله مقارنة رقمين:

 @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) // comparisionResult = .orderedAscending 

سمة غير معروفة في التبديل ( SE-0192 )


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

سيضيف Swift 5 السمة غير المعروفة ، مما سيتيح لك فصل سيناريوهين مختلفين عند معالجة التعداد:

  • يجب تنفيذ التعليمات البرمجية الافتراضية في جميع الحالات التي لم تتم معالجتها بتبديل
  • تتم معالجة جميع الحالات في التبديل ، وإذا تمت إضافة حالات جديدة ، فأنت بحاجة إلى استخدام الرمز بشكل افتراضي

لنلقِ نظرة على مثال:

 enum HTTPMethod { case post, get, put } //  @unknown switch httpMethod { case .post: print("Post") case .get: print("Get") default: print("Put") } //  @unknown switch httpMethod { case .post: print("Post") case .get: print("Get") @unknown default: print("Unknown HTTP method") } 

التخلص من ضعف اختياري نتيجة لاستدعاء وظيفة مع محاولة؟ ( SE-0230 )


بالتأكيد صادف الكثيرون حقيقة أنه عند استدعاء وظيفة رمي ، والتي تعود اختياري ، باستخدام محاولة؟ ، والنتيجة هي نوع ملفوف في اثنين اختياري . هذه ليست مريحة للغاية ، وحتى في سويفت 5 ، اتصل محاولة؟ في هذه الحالة سيعود نوع ملفوف في واحد اختياري فقط.

هكذا كان الحال قبل Swift 5:

 let result = try? optionalObject?.foo() // type(of: result) = SomeType?? 

وهكذا سيكون في Swift 5:

 let result = try? optionalObject?.foo() // type(of: result) = SomeType? 

تحقق التعددية ( SE-0225 )


للتحقق من تعدد رقم لآخر ، يمكنك استخدام isMultiple (of :) ، بدلاً من باقي القسمة (٪):

 //   let isEven = 4 % 2 == 0 //   let isEvent = 4.isMultiple(of: 2) 

التغيير بسيط ، لكنه يجعل الكود أكثر وضوحًا ويبسط عملية البحث عن طريق الكود.

حساب عدد العناصر في تسلسل مع شرط ( SE-0220 )


في Swift 5 ، سيضيف نوع التسلسل العد (حيث: (العنصر) -> Bool) -> طريقة ، والتي سوف تتيح لك حساب عدد العناصر في تسلسل تفي بشرط معين في مرور واحد. قبل ذلك ، اضطررت إلى استخدام مرشح بالتزامن مع العد . ستوفر هذه الطريقة الذاكرة المخصصة عند إنشاء صفيف جديد في طريقة التصفية .

مثال:

 let countOfZeroes = [0, 1, 2, 0, 4].count(where: { $0 == 0 }) // countOfZeroes = 2 

طريقة CompactMapValues ​​في القاموس ( SE-0218 )


هذه الطريقة تجمع بين compMap من Array و mapValues من القاموس . نتيجة لاستدعاء هذه الطريقة ، يتم إنشاء قاموس ذو قيم محولة لا توجد فيه قيم تساوي الصفر .

مثال:

 let dictionary = ["a": "1", "b": "2", "c": "Number"] let resultDictionary = dictionary.compactMapValues { Int($0) } // resultDictionary = ["a": 1, "b": 2] 

أوتار خام ( SE-0200 )


أضيفت القدرة على كتابة السطور التي تستخدم فيها علامات الاقتباس و الشرطة المائلة للخلف كأحرف عادية ، وليس كأحرف خاصة. للقيام بذلك ، أضف الحرف # في بداية ونهاية السطر.

مثال:

 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 ؛ حيث يتم جمع التغييرات الرئيسية فقط هنا. بشكل عام ، تكون التغييرات المقدمة إيجابية وتجعل اللغة أكثر قابلية للفهم ومرونة. الشيء الرئيسي هو أن "تحويل إلى صيغة سويفت الحالية" يجب أن تكون غير مؤلمة.

هذا كل شيء ، شكرا للقراءة.

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


All Articles