Swift 4.0 مقابل Swift 3.0 - الاختلافات والميزات الجديدة
نشرت: 2021-10-05لقد وصلنا أخيرًا اليوم الذي أصدرت فيه Apple إصدارًا جديدًا من لغة Swift المعروفة. ماذا نتوقع منه؟ أثناء ارتجاف الترقب ، قررنا تقديم نظرة عامة صغيرة على التحديثات الجديدة التي ستكون موجودة في إصدار Swift 4 .
3 ركائز سويفت.
كلغة رائعة للكتابة عليها ، فإن Swift لها فوائدها الخاصة ، ويُزعم أنها "تعمر" لغة Objective-C.
نرحب بقراءة الاختلافات الرئيسية بين Swift و Objective-C
سويفت سريع، النوع آمن ومعبرة جدا. يمكن استخدامه لكتابة البرامج على الهواتف والأجهزة اللوحية وأجهزة سطح المكتب والخوادم - على ما يبدو ، على كل ما يشغل الكود. يرحب بك للعب بها - باستخدام تطبيق Swift Playgrounds الخاص بتعلم كيفية كتابة التعليمات البرمجية من Apple أو باستخدام Playgrounds في Xcode ، ستتمكن من رؤية نتائج عملك على الفور ، ولا داعي للتوقف عن تطوير تطبيق وتشغيله على المركز الأول. مع كل إصدار مضاف جديد يصبح أفضل وأسرع ، وهذا هو الحال مع إصدار Swift 4.
استعداد ثابت؟
ميزة أخرى رائعة يمتلكها Xcode 9 لـ Swift 4 - لا داعي للقلق كثيرًا بشأن الترحيل القادم وستكتشف السبب أثناء قراءة هذا المقال.
بالحديث عن ذلك ، دعنا نستكشف بإيجاز ما الذي تجلبه لنا ميزات Bonbons و Swift 4 الجديدة هذا الخريف.
ابدء
اللغة نفسها ليست مفيدة جدًا بدون IDE سهل الاستخدام ، وهو Xcode في عالم المطورين. يمكنك تنزيل أحدث إصدار من Xcode 9 من Mac App Store أو من صفحة التنزيلات على موقع Apple Developer ، ولكن تأكد أولاً من أن لديك حساب مطور نشط. إنه مستقر جدًا لذا يمكنك استبدال Xcode 8 به في إجراءات الترميز اليومية.
يمكنك أيضًا تثبيت إصدارات متعددة من Xcode باستخدام xcversion
إذا كنت تبدأ مشروعًا جديدًا - فأنت على ما يرام. ولكن إذا كان لديك بالفعل مشروع مكتوب بلغة Swift 3.x - فيجب أن تمر بعملية الترحيل.
نوصي بالتجربة أولاً في Playground - للتعود على استخدام الميزات الجديدة.
ستلاحظ روابط لمقترحات Swift Evolution بتنسيق "SE -____" أثناء قراءة هذه المقالة.
الهجرة إلى Swift 4
لطالما كان الترحيل من إصدار رئيسي من Swift إلى الإصدار التالي مكثفًا للغاية ، خاصة من Swift 2.x إلى 3.0. عادةً ما يستغرق الأمر حوالي يوم إلى يومين لكل مشروع ، ولكن الترحيل إلى Swift 4 أسهل قليلاً ويمكن تمريره بشكل أسرع.
إعداد ما قبل الهجرة
لا يدعم Xcode 9 Swift 4 فحسب ، بل يدعم الإصدار الانتقالي 3.2 أيضًا ، لذلك يجب أن يتم تجميع مشروعك دون أي صعوبات قاسية. هذا ممكن لأن مترجم Swift 4 وأداة الترحيل يدعم كلا الإصدارين من اللغة. يمكنك تحديد إصدارات Swift مختلفة لكل هدف ، وهذا مفيد للغاية إذا لم يتم تحديث بعض مكتبات الجهات الخارجية بعد أو إذا كان لديك أهداف متعددة في مشروعك. ومع ذلك ، ليس فقط اللغة ، ولكن SDK قد حصلت أيضًا على بعض التغييرات ، لذلك من المحتمل جدًا أن يتم تطبيق بعض التحديثات على الكود الخاص بك بينما تواصل Apple إدارة واجهات برمجة تطبيقات SDK ...
أداة الترحيل السريع
كما هو الحال دائمًا ، توفر Apple أداة ترحيل Swift مجمعة داخل Xcode والتي يمكن أن تساعد في الترحيل من إصدار Swift السابق. يمكنك تشغيله في Xcode بالانتقال إلى Edit -> Convert -> To Current Swift Syntax ... وتحديد الأهداف التي تريد تحويلها.
سيتم سؤالك بعد ذلك عن تفضيل الاستدلال Objective-C الذي تريد تطبيقه:
نظرًا لأن التغييرات الإضافية تهيمن على Swift 4 ، فإن أداة الترحيل Swift ستدير معظم التغييرات نيابةً عنك.
CocoaPods
يستخدم معظم المطورين مدير تبعية CocoaPods لمشاريعهم لأن Swift Package Manager ليس ناضجًا كما ينبغي ، على الرغم من أنه يتحسن بسرعة كبيرة. كما هو مذكور أعلاه ، لم يتم تحديث جميع مكتبات الجهات الخارجية إلى Swift 4 حتى الآن ، لذلك يمكنك رؤية أخطاء أثناء تجميع بعضها. أحد الحلول الممكنة لإصلاح هذه المشكلة هو تحديد Swift الإصدار 3.2 لتلك البودات التي لم يتم تحديثها بعد عن طريق إضافة post_install برمجي post_install إلى Podfile :
old_swift_3_pods = [ 'PodName1', 'PodName2', ] post_install do |installer| installer.pods_project.targets.each do |target| if old_swift_3_pods.include? target.name target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '3.2' end end end endثم اركض
pod installالآن يمكنك تجميع البودات بدون أخطاء.
دعنا نفحص التغييرات والإضافات في Swift 4 API.
تغييرات وإضافات API
سلاسل
تتوافق String الآن مع بروتوكول Collection بفضل اقتراح SE-0163. هل تتذكر Swift 1.x؟
ليست هناك حاجة لخاصية مجموعة characters الآن حيث يمكنك التكرار عبر String مباشرة:
let string = "Hello, Mind Studios!" for character in string { print(character) } هذا أيضا يعني أنه يمكنك استخدام أي Collection الأساليب والخصائص في String ، مثل count ، isEmpty ، map() ، filter() ، index(of:) وغيرها الكثير:
string.count // No more `string.characters.count` string.isEmpty // false let index = string.index(of: " ") // 6 let reversedCollection = "abc".reversed() let reversedString = String(reversedCollection) // "cba" // String filtering let string = "ni123n456iniASijasod! 78a9-kasd aosd0" let numbersString = string.filter { Int(String($0)) != nil } // "1234567890" نوع Substring جديدة
يجلب Swift 4 نوع Substring جديدًا يمثل Substring من String (كما هو موضح في SE-0163 المذكور أعلاه).
// Split string into substrings let string = "Hello, Mind Studios!" let parts = string.split(separator: " ") // ["Hello,", "Mind", "Studios!"] type(of: parts.first!) // Substring.Type يدعم كل من String و Substring الآن StringProtocol الجديد مما يجعلها متطابقة تقريبًا وقابلة للتشغيل المتبادل:
var hello = parts.first! // Concatenate a String onto a Substring hello += " !" // "Hello, !" // Create a String from a Substring let helloDog = String(hello) // "Hello, !"ملاحظة مهمة
SE-0163 لديه ملاحظة مهمة للغاية:
Long-term storage of `Substring` instances is discouraged. A substring holds a reference to the entire storage of a larger string, not just to the portion it presents, even after the original string's lifetime ends. Long-term storage of a substring may therefore prolong the lifetime of elements that are no longer otherwise accessible, which can appear to be memory leakage. مما يعني أن المقصود استخدام String Substring مؤقت String اللاحقة. إذا كنت ترغب في تمريرها إلى بعض العمليات أو الفئات الأخرى - قم بتحويلها إلى String أولاً:
let substring: Substring = ... // Substring let string = String(substring) // String someMethod(string) على أي حال ، سيساعدك نظام الكتابة في Swift على عدم تمرير Substring مكان ما حيث يتوقع String (على افتراض أنك لا تستخدم StringProtocol الجديد كنوع معلمة).
سلسلة حرفية متعددة الأسطر
يقدم SE-0168 بنية بسيطة لسلسلة حرفية متعددة الأسطر باستخدام ثلاث علامات اقتباس مزدوجة """ مما يعني أنه يمكن لصق معظم تنسيقات النص (مثل JSON أو HTML) أو بعض النصوص الطويلة دون أي هروب:
let multilineString = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mattis lorem et leo laoreet fermentum. Mauris pretium enim ac mi tempor viverra et fermentum nisl. Sed diam nibh, posuere non lectus at, ornare bibendum erat. Fusce mattis sem ac feugiat vulputate. Morbi at nunc maximus, vestibulum orci et, dictum neque. Vestibulum vulputate augue ac libero vulputate vestibulum. Nullam blandit et sapien non fermentum. Proin mollis nisl at vulputate euismod. """الهروب من الأسطر الجديدة في السلاسل الحرفية
يضيف SE-0182 القدرة على الهروب من الأسطر الجديدة في سلسلة حرفية متعددة الأسطر بخط مائل عكسي في نهاية السطر.
let escapedNewline = """ Line 1, Line 2 \ next part of line 2, Line 3 """ print(escapedNewline) Line 1, Line 2 next part of line 2, Line 3تحسين دعم Unicode
يوفر Swift 4 دعمًا لـ Unicode 9 مما يعني أن المشكلات المتعلقة بحساب أحرف unicode قد ولت الآن:
"".count // 1, in Swift 3: 2 "".count // 1, in Swift 3: 2 "".count // 1, in Swift 3: 2 - person + skin tone "".count // 1, in Swift 3: 4 "".count // 3, in Swift 3: 1جميع التغييرات والمقترحات المنفذة التي تم إبرازها أعلاه (مثل العديد من الآخرين) تأخذ جذورها من مجموعة موصوفة على نطاق واسع من الميزات تسمى بيان السلسلة.
صلاحية التحكم صلاحية الدخول
جلبت سويفت 3 عنصر متناقضة جدا لمراقبة الدخول - fileprivate معدل الوصول التي يمكن أن تكون مربكة حقا.
في السابق ، تم استخدام معدِّل مستوى الوصول private لإخفاء أعضاء النوع من الأنواع الأخرى ، ولا يمكن الوصول إلى الأعضاء الخاصين إلا من خلال الأساليب والخصائص المحددة في تعريف النوع ، مع ترك نفس ملحقات النوع جانبًا حيث لا يمكنهم الوصول إلى هؤلاء الأعضاء.
يمكن استخدام fileprivate لمشاركة الوصول لأعضاء النوع ، مثل الخصائص والأساليب ، داخل نفس الملف.
في الواقع ، أدى استخدام private إلى مشكلة عندما لا تتمكن الإضافات من نوع ما من الوصول إلى أعضاء من هذا النوع ، لذلك كان استخدام fileprivate في مثل هذه الظروف حلاً شائعًا للغاية ، مما أدى إلى مشكلة أخرى: أنواع أخرى في نفس الملف يمكنه الوصول إلى هؤلاء الأعضاء أيضًا.
يقوم Swift 4 بترتيب الأشياء من خلال السماح للامتدادات على النوع بالوصول إلى الأعضاء private من هذا النوع في نفس الملف كما هو موضح في SE-0169:
struct User { private let firstName: String private let lastName: String } extension User: CustomStringConvertible { var description: String { return "User: \(firstName) \(lastName)" } }القاموس والمجموعة
تهيئة Dictionary Sequence
Dictionary يمكن تهيئة مع Sequence الآن، ولكن يمكن أن تنتقل ليس كل متواليات في هذا مهيئ، فقط تلك التي تحتوي على الصفوف (Key, Value) ، حيث Key هو نوع رئيسي من القاموس و Value تمثل القاموس نوع القيمة:
let stocksIdentifiers = ["AAPL", "GOOGL", "NKE"] let stocksValues = [158.28, 940.13, 53.73] let pairs = zip(stocksIdentifiers, stocksValues) let stocksValuesDict = Dictionary(uniqueKeysWithValues: pairs) // ["GOOGL": 940.13, "NKE": 53.73, "AAPL": 158.28] هنا تقوم وظيفة zip بإنشاء زوج ( Tuple s) من تسلسلين ، يمكنك قراءة المزيد حول هذه الوظيفة في وثائق Swift Standard Library.
دمج القواميس
يمكنك تحديد كيفية معالجة المفاتيح المكررة عند إنشاء قاموس من تسلسل Tuple s عن طريق تمرير الإغلاق إلى المعلمة uniquingKeysWith ، والتي تُستخدم لدمج القيم من مفتاحين متطابقين.
مثال 1:
let duplicates = [("a", 1), ("b", 5), ("a", 3), ("b", 3)] let dictionary = Dictionary(duplicates, uniquingKeysWith: { (first, _) in return first }) // ["b": 5, "a": 1]هنا نترك القيمة الأولى متجاهلة جميع القيم التالية بنفس المفتاح.
المثال 2:
حساب عدد مرات ظهور كل حرف في السلسلة.
let string = "Hello!" let pairs = Array(zip(string, repeatElement(1, count: string.count))) let counts = Dictionary(pairs, uniquingKeysWith: +) // ["H": 1, "e": 1, "o": 1, "l": 2, "!": 1]المثال 3:
باستخدام طريقة merge :
let values = ["a": 1, "b": 5] var additionalValues = ["b": 3, "c": 2, "a": 3] additionalValues.merge(values, uniquingKeysWith: +) // ["b": 8, "c": 2, "a": 4]منخفض بقيمة افتراضية
في السابق ، كان من الممارسات الشائعة استخدام عامل الاندماج الصفري لإعطاء قيمة افتراضية في حالة عدم وجود القيمة.
سويفت 3:
let dict = ["a": 1, "b": 5] dict["c"] ?? 0 // 0 يقدم Swift 4 قيمة default جديدة على الاشتراكات (جزء من SE-0165):
let dict = ["a": 1, "b": 5] dict["c", default: 0] // 0, equals to `dict["c"] ?? 0` in Swift 3يمكنك أيضًا تغيير القاموس أثناء تسجيله بقيمة افتراضية:
let string = """ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam mattis lorem et leo laoreet fermentum. Mauris pretium enim ac mi tempor viverra et fermentum nisl. Sed diam nibh, posuere non lectus at, ornare bibendum erat. Fusce mattis sem ac feugiat vulputate. Morbi at nunc maximus, vestibulum orci et, dictum neque. Vestibulum vulputate augue ac libero vulputate vestibulum. Nullam blandit et sapien non fermentum. Proin mollis nisl at vulputate euismod. """ var wordsCountByLine = [Int: Int]() let lines = string.split(separator: "\n") for (index, line) in lines.enumerated() { let lineWordsCount = line.split(separator: " ").count wordsCountByLine[index, default: 0] += lineWordsCount } print(wordsCountByLine) // [2: 10, 4: 15, 5: 7, 6: 6, 7: 6, 0: 8, 1: 7, 3: 10]خريطة وفلتر خاص بالقاموس
تجميع عناصر التسلسل
أنواع مرتبطة مقيدة في البروتوكولات
يقدم الاقتراح SE-0142 إضافة عبارات شرطية إلى إقرارات النوع المرتبطة.

extension Sequence where Element: Numeric { var sum: Element { var result: Element = 0 for element in self { result += element } return result } } [1,2,3,4].sumالأرشفة والتسلسل (الترميز / فك التشفير)
في السابق ، من أجل إجراء تسلسل لبعض NSCoding المخصصة ، يجب عليك استخدام بروتوكول NSCoding القديم والمعروف. تكمن المشكلة في أن الأنواع غير الطبقية مثل struct enum لا تتوافق مع هذا البروتوكول ، لذلك لم يكن لدى المطورين ما يفعلونه سوى استخدام الاختراقات مثل توفير طبقة إضافية من التوافق من خلال إنشاء فئة متداخلة يمكن أن تتوافق مع NSCoding .
يحتوي Swift 4 على حل مناسب جدًا لهذه المشكلة بفضل SE-0166 - مقدمة لبروتوكول Codable :
struct Employee: Codable { let name: String let age: Int let role: Role enum Role: String, Codable { case manager case developer case admin } } struct Company { let name: String let officeLocation: Location? let employees: [Employee] } struct Location : Codable { let latitude: Double let longitude: Double } في حالة بسيطة مثل هذه ، كل ما تحتاجه هو إضافة مطابقة بروتوكول Codable لجميع الأنواع المخصصة الخاصة بك ، سيقوم المترجم بعمل السحر من أجلك. هذا كل شيء!
Codable هو typealias لتكوين Decodable و Encodable البروتوكولات، حتى تتمكن من إعلان، على سبيل المثال، فقط Decodable التوافق بروتوكول إذا كنت تريد فك المثال النوع الخاص من البيانات JSON.
التشفير
إذا كنت ترغب في إجراء تسلسل أو إلغاء تسلسل قيمة Codable - يجب عليك استخدام كائن وحدة فك التشفير أو وحدة فك التشفير. يأتي Swift 4 بالفعل مع مجموعة من أجهزة التشفير / أجهزة فك التشفير لـ JSON وقوائم الخصائص بالإضافة إلى CocoaError الجديدة لأنواع مختلفة من الأخطاء التي يمكن إلقاؤها أثناء التشفير / فك التشفير. NSKeyedArchiver & NSKeyedUnarchiver أيضًا الأنواع Codable .
let employee = Employee(name: "Peter", age: 27, role: .manager) let company = Company(name: "Awesome Company", officeLocation: nil, employees: [employee]) let encoder = JSONEncoder() let companyData = try encoder.encode(company) let string = String(data: companyData, encoding: .utf8)! print(string) >>> { "name" : "Awesome Company", "employees" : [ { "name" : "Peter", "age" : 27, "role" : "manager" } ] }قطعة من الكعكة ، أليس كذلك؟ A piece of cake، isn't it؟
فك
يتم استخدام وحدة فك التشفير Codable تسلسل نوع Codable مخصص من Data . إنه لا يعرف النوع المطلوب فك تشفيره من البيانات نفسها ، لذلك يجب تحديد النوع المطلوب فك تشفيره ، على سبيل المثال ، Employee أو [Employee] :
let decoder = JSONDecoder() let jsonData = """ [ { "name" : "Peter", "age" : 27, "role" : "manager" }, { "name" : "Alex", "age" : 26, "role" : "developer" }, { "name" : "Eugene", "age" : 30, "role" : "admin" } ] """.data(using: .utf8)! let employees = try decoder.decode([Employee].self, from: jsonData) If one of `Codable` type instances fails to decode, then whole collection will fail to decode.أسماء المفاتيح المخصصة
في معظم الحالات ، لا تتطابق الأسماء التي نستخدمها في أنواع Swift المخصصة مع المفاتيح الموجودة في بيانات JSON التي تمثل هذا النوع. لإنشاء تعيين بين أسماء خصائص النوع المخصص ومفاتيح JSON ، يمكنك إنشاء تعداد متداخل يسمى CodingKeys والذي يجب أن يتوافق مع بروتوكول CodingKey :
struct Country: Decodable { let id: String let name: String let phoneCode: String private enum CodingKeys: String, CodingKey { case id = "alpha3" case name case phoneCode = "phone_code" } }فك مخصص
إذا كانت لديك حالة معقدة ، فيمكنك تنفيذ Decodable المخصص من بروتوكول Decodable :
struct Transaction { let id: Int let action: String let source: String let amount: Int let state: TransactionState let createdAt: Date let authorName: String enum TransactionState: String, Decodable { case done case canceled case processed } } extension Transaction: Decodable { private enum CodingKeys: String, CodingKey { case id case action = "action_name" case source = "source_name" case amount case state case createdAt = "created_at" case author } private enum AuthorKeys: String, CodingKey { case fullName = "full_name" } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) id = try container.decode(Int.self, forKey: .id) actionName = try container.decode(String.self, forKey: .action) sourceName = try container.decode(String.self, forKey: .source) let createdAtValue = try container.decode(Double.self, forKey: .createdAt) createdAt = Date(timeIntervalSince1970: createdAtValue) state = try container.decode(TransactionState.self, forKey: .state) amount = try container.decodeIfPresent(Int.self, forKey: .amount) ?? 0 do { let authorContainer = try container.nestedContainer(keyedBy: AuthorKeys.self, forKey: .author) authorName = try authorContainer.decode(String.self, forKey: .fullName) } catch { authorName = "" } } }ترميز القيمة الرئيسية
إحدى الميزات المفيدة التي توفرها Swift 4 هي Smart KeyPaths الموضحة في SE-0161. على عكس Swift 3 #keyPath() ، والذي لا يتم كتابته بقوة ويعمل فقط مع أعضاء Objective-C ، فإن Swift 4 KeyPath هو فئة عامة ، مما يعني أن المسارات الرئيسية مكتوبة الآن بقوة. دعنا نتعمق في بعض الأمثلة:
struct User { var username: String } الشكل العام لمسار المفتاح \<Type>.<path> ، حيث <Type> هو اسم نوع ، و <path> هو سلسلة من خاصية واحدة أو أكثر ، على سبيل المثال ، \User.username :
let user = User(username: "max") let username = user[keyPath: \User.username] // "max"يمكنك أيضًا كتابة قيمة جديدة من خلال مسار المفتاح هذا إذا كان قابلاً للتغيير:
var user = User(username: "max") user[keyPath: \User.username] = "alex" // "alex"لا تقتصر المسارات الرئيسية على مستوى واحد من التسلسل الهرمي:
struct Comment { let content: String var author: User } let max = User(username: "max") let comment = Comment(content: "Nice post!", author: max) let authorUsername = comment[keyPath: \Comment.author.username] // "max"يمكن تخزين المسارات الرئيسية في متغير:
let authorKeyPath = \Comment.author let usernameKeyPath = authorKeyPath.appending(path: \.username) let authorUsername = comment[keyPath: usernameKeyPath] // "max"يمكنك أيضًا استخدام مسارات المفاتيح للخصائص الاختيارية والمحسوبة:
struct Post { let title: String var comments: [Comment] var topComment: Comment? { return comments.first } } let max = User(username: "max") let alex = User(username: "alex") var post = Post(title: "What's new in Swift 4", comments: []) let topCommentAuthorUsernameKeyPath = \Post.topComment?.author.username post[keyPath: topCommentAuthorUsernameKeyPath] // nil let comment = Comment(content: "", author: alex) let anotherComment = Comment(content: "Nice post!", author: max) post.comments = [comment, anotherComment] post[keyPath: topCommentAuthorUsernameKeyPath] // "alex"على الرغم من أن SE-0161 يسلط الضوء على رموز الدعم في المسارات الرئيسية ، إلا أنه لم يتم تنفيذها بعد:
post.comments[keyPath: \.[0].content] // error: key path support for subscript components is not implemented let firstCommentAuthorKeyPath = \Post.comments[0].author // error: key path support for subscript components is not implementedKVO
بالإضافة إلى المسارات الرئيسية الجديدة ، تم تحديث واجهة برمجة تطبيقات مراقبة القيمة الرئيسية في Swift 4 أيضًا.
New KVO APIs depend on Objective-C runtime and works for `NSObject` subclasses only, so it can't be used for Swift structs and classes which don't inherit `NSObject`. In order to observe property it should be marked as `@objc dynamic var`. class User: NSObject { @objc dynamic var name: String var username: String init(name: String, username: String) { self.name = name self.userName = userName super.init() } } let user = User(name: "Max", username: "max") let nameObservation = user.observe(\.name, options: [.new, .old]) { user, change in // NSKeyValueObservation if let oldValue = change.oldValue, let newValue = change.newValue { print("fullName has changed from \(oldValue) to \(newValue)") } else { print("fullName is now \(user.name)") } } user.name = "Alex" // name has changed from Max to Alex استدعاء أسلوب invalidate() إذا كنت تريد إيقاف الملاحظة
nameObservation.invalidate() user.name = "Elina" // observer isn't get calledيتم إيقافه أيضًا عند تحديده ، لذا تأكد من تخزينه في الممتلكات أو في مكان آخر إذا كنت تريد الاحتفاظ به.
نطاقات من جانب واحد
يقدم SE-0172 نطاقات "أحادية الجانب" ، تم إنشاؤها عبر إصدارات بادئة / RangeExpression لمشغلي النطاق الحاليين ، وبروتوكول RangeExpression جديدًا لتبسيط إنشاء الطرق التي تأخذ أنواعًا مختلفة من النطاقات.
التسلسلات اللانهائية
يمكنك استخدام نطاق أحادي الجانب لإنشاء تسلسل لا نهائي:
let letters = ["a", "b", "c", "d"] let numberedLetters = Array(zip(1..., letters)) // [(1, "a"), (2, "b"), (3, "c"), (4, "d")] let string = "Hello, Mind Studios!" let index = string.index(of: ",")! string[..<index] // "Hello" string[...index] // "Hello,"استخدام نطاقات من جانب واحد في مطابقة الأنماط
let value = 5 switch value { case 1...: print("greater than zero") case 0: print("zero") case ..<0: print("less than zero") default: break }نصوص عامة
يمكن أن تحتوي النصوص الفرعية SE-0148 الآن على وسيطات عامة وأنواع إرجاع
struct JSON { let data: [String: Any] subscript<T>(key: String) -> T? { return data[key] as? T } } let jsonDictionary: [String: Any] = [ "name": "Ukraine", "flag": "", "population": 42_500_000 ] let json = JSON(data: jsonDictionary) let population: Int? = json["population"] // 42500600 extension Dictionary where Value == String { subscript<T: RawRepresentable>(key: Key) -> T? where T.RawValue == Value { guard let string = self[key] else { return nil } return T(rawValue: string) } } enum Color: String { case red case green case blue } let dictionary = [1: "red"] let color: Color? = dictionary[1] // redالحد من الاستدلال الموضوعي
يقلل Swift 4 من استدلالobjc من خلال قصره على تلك الحالات فقط عندما يكون الإعلان متاحًا لـ Objective-C (SE-0160).
يؤدي ذلك إلى تقليل الحجم الثنائي لتطبيقك من خلال عدم تجميع كود Objective-C المكرر إذا لم تستخدمه ، ويمنحك مزيدًا من التحكم في وقت استنتاجobjc. لم تعد الفئات المشتقة من NSObject تستنتجobjc.
ولكن هناك بعض المواقف التي سيستمر فيها رمز Swift في الحصول على استنتاج ضمني:
التصريحات التي لها سمةobjc
الإعلانات التي تفي بمتطلبات بروتوكولobjc
التصريحات التي لها سماتIBAction وIBInspectable وIBOutlet وNSManaged وGKInspectable
لتمكين الاستدلالobjc لفصل دراسي بأكمله ، يمكنك استخدام السمةobjcmembers الجديدة.
لتعطيل استنتاجobjc لملحق أو وظيفة معينة - أضف السمةnonobjc الجديدة.
يؤلف الطبقات والبروتوكولات
في Swift 4 يمكننا الآن إنشاء بروتوكولات مع أنواع Swift الأخرى:
User & Codable & CustomStringConvertible typealias MyType = User & Codable & CustomStringConvertibleفوائد Swift 4.
مزايا Swift 4 هائلة حقًا ، كما يحدث غالبًا عندما تصدر Apple إصدارًا جديدًا للغة. بصرف النظر عن الأداء اللغوي المحسن ، فقد أدى أيضًا إلى استقرار عملية الترحيل بشكل كبير. بإعادة عقولنا إلى عملية ترحيل Swift 2.2 إلى 3.0 ، نتذكر العملية المعقدة المتمثلة في نقل جميع التبعيات. تتيح لنا تغييرات Swift 4.0 مغادرة مكتبات الجهات الخارجية دون "نقلها" فعليًا - ما عليك سوى تحديث Swift نفسها.
أيضًا فيما يتعلق بتحسينات Swift 4.0 مقابل 3.0 ، تم تغيير حجم الملفات الثنائية المجمعة ، مما أدى إلى تقليل حجم التطبيق ؛ على سبيل المثال ، تطبيق الهاتف المحمول المستخدم بوزن 20 ميغا بايت ، وفي أحدث إصدار من Swift سيستغرق حوالي 17 ميغا بايت. وهناك فرق أساسي بين Swift 4 و Swift 3 - حدث إصلاح الخلل ، وأصبحت اللغة أسرع قليلاً.
لقد مرت سنوات منذ أن تم استخدام Swift ، ويستمر في التطور مع كل تحديث قادم. مع تجديد كل لغة جديدة ، تظهر آفاق تطوير جديدة ، لم تكن معروفة من قبل ، ونتطلع إلى استكشاف آفاق جديدة لنظام iOS.
لا تفوت مقالتنا حول MVP و MVC و MVVM و VIPER لتطوير iOS.
بقلم ماكس مشكوف وإيلينا بيسارابوفا .
