Swift 5 What’s new?
- Tram Ho
) { $0[$1.key] = Int($1.value) } // [“Oana”: “10”]
Swift 5 dùng compactMapValues(_:)
để giải quyết vấn đề trên (xem chi tiết tại đây):
1 | let mapStudents = students.compactMapValues(Int.init) |
7. Renaming Dictionary Literals
Swift 4.2 dùng DictionaryLiteral để khai báo cho 1 từ điển:
1 | let pets: DictionaryLiteral = ["dog": "Sclip", "cat": "Peti"] |
Note: DictionaryLiteral không phải là một dictionary hoặc 1 literal. Nó là 1 list các cặp key-value.
Swift 5 đã đổi tên DictionaryLiteral thành KeyValuePairs: let pets: KeyValuePairs = [“dog”: “Sclip”, “cat”: “Peti”]
8. Handling Future Enumeration Cases
swift 4.2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // 1 enum Post { case tutorial, article, screencast, course } // 2 func readPost(_ post: Post) -> String { switch post { case .tutorial: return "You are reading a tutorial." case .article: return "You are reading an article." default: return "You are watching a video." } } // 3 let screencast = Post.screencast readPost(screencast) // "You are watching a video." let course = Post.course readPost(course) // "You are watching a video." |
Trong swift 5 sẽ bổ sung đánh dấu các giá trị đang để mặc định để trong tương lai bạn có thể thay các giá trị đang là default của enum thành các giá trị cụ thể bằng cách báo warning của Xcode:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | func readPost(_ post: BlogPost) -> String { switch post { case .tutorial: return "You are reading a tutorial." case .article: return "You are reading an article." @unknown default: return "You are reading a blog post." } } readPost(screencast) // "You are reading a blog post." readPost(course) // "You are reading a blog post." readPost(podcast) // "You are reading a blog post." |
In this code, you mark default as @unknown, and Swift warns you that switch isn’t exhaustive. default handles .screencast, .course and .podcast because screencasts, courses and podcasts are blog posts. Trong đoạn code trên, bạn đánh dấu @unknown, và swift sẽ báo warning rằng : Switch must be exhaustive. Xcode sẽ implement tất cả các enumeration cases của Enum.
9. Adding Result to the Standard Library
Swift 5 thêm Result vào standard library:
- Kiểu Result type handle kết quả của asynchronous function dùng enum với 2 case: success and failure. Để hiểu nó như thế nào mình sẽ đưa ra 1 ví dụ xử lý kết quả trả về khi gọi API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | let url = URL(string: "https://exampleapi.com/data.json")! URLSession.shared.dataTask(with: url) { (data: Data?, response: URLResponse?, error: Error?) in if let error = error { // Handle Error return } guard let response = response else { // Handle Empty Response return } guard let data = data else { // Handle Empty Data return } // Handle Decode Data into Model } |
Từ đoạn code trên để xử lý kết quả trả về chúng ta cần dùng if let hoắc guard để check response status code, data trả về , and decode the data ra thành model. Cách xử lý thanh hơi cồng kềnh, phức tạp. OK! bây giờ các bạn thử dùng type Result trong swift 5 xem nó như thế nào nhé:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | extension URLSession { func dataTask(with url: URL, completion: @escaping (Result<(URLResponse, Data), Error>) -> Void) -> URLSessionDataTask { return dataTask(with: url) { (data, response, error) in if let error = error { completion(.failure(error)) return } guard let response = response, let data = data else { let error = NSError(domain: "error", code: 0, userInfo: nil) completion(.failure(error)) return } completion(.success((response, data))) } } URLSession.shared.dataTask(with: url) { (result) in switch result { case .success(let response, let data): // Handle Data and Response break case .failure(let error): // Handle Error break } } |
Cách này nhìn code khá là clear và dễ hiểu phải không nào.
10. Platform Deployment Settings
Swift 5 cho phép bạn định nghĩa số các platform tối thiểu trong Package.swift
1 2 3 4 5 6 | let package = Package(name: “Package”, platforms: [ .macOS(.v10_14), .iOS(.v12), .tvOS(.v12), .watchOS(.v5) ]) |
Bạn có thể dùng macOS(), iOS(), tvOS() và watchOS() trong SupportedPlatform để set flatform tối thiểu trong Package.swift.
11. Flattening Nested Optionals
Swift 4.2 tạo nested optionals with try? như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | extension Int { // 1 enum DivisionError: Error { case divisionByZero } // 2 func divideBy(_ number: Int) throws -> Int { guard number != 0 else { throw DivisionError.divisionByZero } return self / number } } // 3 let number: Int? = 10 let division = try? number?.divideBy(2) // Kiểu của division là Optional<Optional<Int>> hay chính là kiểu Int?? trong swift 4.2 if let division = division, let final = division { print(final) } |
Tuy nhiên khi lên swift 5 thì nested optionals with try?
1 2 3 4 | // division trong swift 5 chỉ Optional<Int> hay chỉ là kiểu Int? if let division = division { print(division) // Int } |
try? trong swift 5 sẽ không tạo nested optionals , bạn chỉ cần unwrap division 1 lần duy nhất khi nó đang là kiểu Int?
12. Build Configuration Updates
Swift 4.2 dùng >= trong compilation conditions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | let favoriteNumber = 10 var evenNumber = true #if !swift(>=5) evenNumber = favoriteNumber % 2 == 0 #else evenNumber = favoriteNumber.isMultiple(of: 2) #endif #if !compiler(>=5) evenNumber = favoriteNumber % 2 == 0 #else evenNumber = favoriteNumber.isMultiple(of: 2) #endif |
Swift 5 support thêm dấu < trong compilation conditions:
1 2 3 4 5 6 7 8 9 10 11 | #if swift(<5) evenNumber = favoriteNumber % 2 == 0 #else evenNumber = favoriteNumber.isMultiple(of: 2) #endif #if compiler(<5) evenNumber = favoriteNumber % 2 == 0 #else evenNumber = favoriteNumber.isMultiple(of: 2) #endif |
Tài Liệu Tham Khảo
https://www.raywenderlich.com/55728-what-s-new-in-swift-5https://medium.com/@azamsharp/understanding-result-type-in-swift-5-387d5ef9f45e
Swift chen chân vào top 10, Java vẫn giữ vững ngôi vương””]
Apple có ngôn ngữ lập trình Swift thì giờ đây Google cũng có ngôn ngữ lập trình “hạng nhất” cho Android”]
Swift 5 released on March 25, 2019, there are many new features such as Escaping Raw Strings, handling future enumeration, result type … Today I would like to introduce you to read some new features of swift 5 compared. with swift 4.2. Ok, let’s find out!
1. Check integer multiples
Example: To divide a by number in Swift 4.2, you must check whether b is different from 0 or not as follows:
1 2 3 4 5 | let a = 4 let b = 2 if b! = 0 && a% b == 0 { print ("a is a multiple of b") } |
In swift 5: you just need to use isMultiple (of 🙂 function to check if the number a is a multiple of b number?
1 2 3 | if firstNumber.isMultiple (of: secondNumber) { print ("a is a multiple of b") } |
2. Escaping Raw Strings
In Swift 4.2, Escape sequences are using the backslashes ()
and quote marks (“) in strings.
1 2 3 4 5 6 | let escape = "You use escape sequences for" quotes "" backslashes "in Swift 4.2." let multiline = "" " You use escape sequences for "" quotes "" "" "backslashes" " on multiple lines in Swift 4.2. "" " |
Swift 5 can add # at the start and end position of string string when you use backslashes and quote marks
1 2 3 4 5 6 | let raw = # "You can create" raw "" plain "strings in Swift 5." # let multiline = # "" " You can create "" "raw" "" "" "" "strings on multiple lines in Swift 5. "" "# |
Khi sử dụng chuỗi kết hợp với dữ liệu chuỗi, bạn cần dùng một ký tự bảng ở sau backslash: When using string interpolation in raw string VD: "raw string (a)"
, you can use # after the sign
1 2 | let track = "Nothing Else Matters" print (# "My favorite tune is is # (track)." #) |
Note: You can use multiple # sign before the sign “or after the sign
1 2 | let number = 4 let hashtag = ####### "You can use the ####### (number) in Swift 5." ####### // You can use the 4 in Swift 5. |
Print Swift 4.2, you escape backslashes inside regular expressions as follows: In swift 4.2, you escape backslashes ( ) in regular expressions:
1 2 3 4 5 6 7 8 9 | // first let versions = "3 3.1 4 4.1 4.2 5" let range = NSRange (versions.startIndex ..., in: versions) // 2 let regex = try! NSRegularExpression (pattern: "d // 3 let minorVersions = regex.matches (in: versions, range: range) // 4 minorVersions.forEach {print (versions [Range ($ 0.range, in: versions)!])} |
In swift 5 you just write one half slash by replacing by #
1 | let regex = try! NSRegularExpression (pattern: # "d" #) |
3. Use the new character property
In swift 4.2, you convert 1 chracter from String to Int, you do the following:
1 2 3 4 | let id = "ID10" var digits = 0 id.forEach {digits + = Int (String ($ 0))! = nil? ten } print ("Has Id (digits) digits.") |
However, Swift 5 adds the isNumber attribute to check if a character is an Int.
1 | id.forEach {digits + = $ 0.isNumber? ten } |
You can go here to see the new character attributes.
4. Use the new Unicode Scalar Properties
In Swift 4.2, you can check 1 character for example if the character ‘a’ is not a number or not in the following way:
1 2 3 4 5 6 | let username = "bond007" var letters = 0 username.unicodeScalars.forEach { letters + = (65 ... 90) ~ = $ 0.value || (97 ... 122) ~ = $ 0.value? ten } print ("Username has (letters) letters.") |
Swift 5, with new properties, makes handling simpler by using isAlphabetic attributes:
1 | username.unicodeScalars.forEach {letters + = $ 0.properties.isAlphabetic? ten } |
5. Delete Subsequences
In swift 4.2, Subsequences will be returned when Custom Sequences.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | extension Sequence { func remove (_ s: String) -> SubSequence { let guard n = Int (s) else { return dropLast () } return dropLast (n) } } let sequence = [5, 2, 7, 4] sequence.remove ("2") // [5, 2] sequence.remove ("two") // [5, 2, 7] // dropLast (n) function: You understand that deleting characters starting from nth position |
Swift 5, has replaced Subsequences into concrete types (specific types):
1 2 3 4 5 6 7 8 | extension Sequence { func remove (_ s: String) -> [Element] { let guard n = Int (s) else { return dropLast () } return dropLast (n) } } |
6. Compacting Dictionaries
Swift 4.2, use mapValues, filter and reduce to filter the values = nil from dictionary as follows:
1 2 3 4 5 6 | let students = ["Oana": "10", "Nori": "ten"] let filterStudents = students.mapValues (Int.init) .filter {$ 0.value! = nil} .mapValues {$ 0! } // use mapValues to turn dictionary values into Int // then use filter to filter other values nil. let reduceStudents = students.reduce (into: ) {$ 0 [$ 1.key] = Int ($ 1.value)} // ["Oana": "10"] |
Swift 5 uses compactMapValues(_:)
to solve this problem ( see details here ):
1 | let mapStudents = students.compactMapValues (Int.init) |
7. Renaming Dictionary Literals
Swift 4.2 uses DictionaryLiteral to declare for a dictionary:
1 | let pets: DictionaryLiteral = ["dog": "Sclip", "cat": "Peti"] |
Note : DictionaryLiteral is not a dictionary or a literal. It is a list of key-value pairs.
Swift 5 renamed DictionaryLiteral to KeyValuePairs: let pets: KeyValuePairs = [“dog”: “Sclip”, “cat”: “Peti”]
8. Handling Future Enumeration Cases
Swift 4.2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // first enum Post { case tutorial, article, screencast, course } // 2 func readPost (_ post: Post) -> String { post switch { case .tutorial: return "You are reading a tutorial." case .article: return "You are reading an article." default: return "You are watching a video." } } // 3 let screencast = Post.screencast readPost (screencast) // "You are watching a video." let course = Post.course readPost (course) // "You are watching a video." |
In swift 5 will add the value markings that are default so that in the future you can replace the default values of enum to specific values by warning the warning of Xcode:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | func readPost (_ post: BlogPost) -> String { post switch { case .tutorial: return "You are reading a tutorial." case .article: return "You are reading an article." @unknown default: return "You are reading a post blog." } } readPost (screencast) // "You are reading a blog post." readPost (course) // "You are reading a blog post." readPost (podcast) // "You are reading a blog post." |
In code this, you mark default as @unknown , and Swift warns you are not exhaustive. default handles .screencast, .course and .podcast because of the screencasts, courses and podcasts are blog posts. In the above code, you mark @unknown , and swift will warn that: Switch must be exhaustive. Xcode will implement all of Enum’s enumeration cases .
9. Adding Result to the Standard Library
Swift 5 adds Result to the standard library :
- The Result type handle results in asynchronous function using enum with 2 cases: success and failure. To understand how I will give an example to handle the result returned when calling the API:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | let url = URL (string: "https://exampleapi.com/data.json")! URLSession.shared.dataTask (with: url) {(data: Data ?, response: URLResponse ?, error: Error?) Print if let error = error { // Handle Error return } guard let response = câu lệnh khác { // Handle Empty Response return } guard let data = data else { // Handle Empty Data return } // Handle Decode Data into Model } |
From the above code to handle the returned result we need to use guard if let to check response status code, return data, and decode the data to model. How to handle the bar slightly bulky, complex. OK! Now how do you try to use the type Result in swift 5 to see it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | URLSession extension { func dataTask (with url: URL, completion: @escaping (Result <(URLResponse, Data), Error>) -> Void) -> URLSessionDataTask { return dataTask (with: url) {(data, response, error) printed if let error = error { completion (.failure (error)) return } guard let response = response, let data = data else { let error = NSError (domain: "error", code: 0, userInfo: nil) completion (.failure (error)) return } completion (.success ((response, data))) } } URLSession.shared.dataTask (with: url) {(result) prints switch result { case .success (let response, let data): // Handle Data and Response break case .failure (let error): // Handle Error break } } |
This way of looking at the code is quite clear and easy to understand, right.
10. Platform Deployment Settings
Swift 5 allows you to define the minimum number of platforms in Package.swift
1 2 3 4 5 6 | let package = Package (name: "Package", platforms: [ .macOS (.v10_14), .iOS (.v12), .tvOS (.v12), .watchOS (.v5) ]) |
You can use macOS (), iOS (), tvOS () and watchOS () in SupportedPlatform to set the minimum platform in Package.swift.
11. Flattening Nested Optionals
Swift 4.2 creates nested optionals with try? as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | extension Int { // first enum DivisionError: Error { case divisionByZero } // 2 func divideBy (_ number: Int) throws -> Int { guard number! = 0 else { throw DivisionError.divisionByZero } return self / number } } // 3 let number: Int? = 10 let division = try? number? .divideBy (2) // The division type is Optional <Optional <Int>> or Int? in swift 4.2 if let division = division, let final = division { print (final) } |
However, when uploading to swift 5 is nested optionals with try?
1 2 3 4 | // division in swift 5 only Optional <Int> or just Int? if let division = division { print (division) // Int } |
try? in swift 5 will not create nested optionals, you just need to unwrap division once only when it is Int?
12. Build Configuration Updates
Swift 4.2 uses> = in compilation conditions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | let favoriteNumber = 10 var evenNumber = true #if! swift (> = 5) evenNumber = favoriteNumber% 2 == 0 #else evenNumber = favoriteNumber.isMultiple (of: 2) #endif #if! compiler (> = 5) evenNumber = favoriteNumber% 2 == 0 #else evenNumber = favoriteNumber.isMultiple (of: 2) #endif |
Swift 5 support adds <in compilation conditions:
1 2 3 4 5 6 7 8 9 10 11 | #if swift (<5) evenNumber = favoriteNumber% 2 == 0 #else evenNumber = favoriteNumber.isMultiple (of: 2) #endif #if compiler (<5) evenNumber = favoriteNumber% 2 == 0 #else evenNumber = favoriteNumber.isMultiple (of: 2) #endif |
References
https://www.raywenderlich.com/55728-what-s-new-in-swift-5 https://medium.com/@azamsharp/understanding-result-type-in-swift-5-387d5ef9f45e
Swift stepped into the top 10, Java still held the throne. “]]
Apple has a Swift programming language, Google now has a “first-class” programming language for Android “]
Source : viblo