Introduction:
The latest version of Swift programming language, Swift 5.0 is released in March 2019. It is available in Xcode 10.2. One of the main features of Swift 5 is ABI Stability which provides binary compatibility between applications and swift libraries which is compiled in a different version of the Swift language.ABI
ABI stands for Application Binary Interface. Application Binary Interface defines how application data and its structures are accessed in machine code, how data is provided as input and read as an output. It defines low-level details such as how a function is called, what arguments are passed, how data occupies memory and how to access it. The main advantage of ABI stability is that developers don’t have to worry about swift new version compatibility of their app. It also reduces the size of the application because there is no need to add Swift standard library in the framework folder and also language changes become smaller and less frequent. Below is some new features in Swift 5.0.Enhancing Raw String
An escape character (\) is used to create a special interpretation of subsequent characters within a string literal in Swift 4.2. We use escape sequences like \”, \\ and \u{n} to represent quotes, backslashes, and Unicode as follow.let string = "This is the string example with \"quotes\" and backslashes(\\)" //output : This the string example with “quotes” and backslashes(\) let multiline = """ \"This is the multiline string example with more \"quotes\" and \"backslashes\"(\\)\" """ //output : This is the // multiline string example // with more “quotes” and “backslashes”(\)
In Swift 5.0, no need to use this. A raw string literal is used to ignore the escape sequence. Quotes and backslashes can be used by adding # before and after string as follow.
let string = #"This is the string example with “quotes” and backslashes(\)"# //output : This the string example with “quotes” and backslashes(\) let multiline = #""" "This is the multiline string example with more "quotes" and "backslashes"(\)" """# //output : This is the // multiline string example // with more “quotes” and “backslashes”(\)
If there is # in your string then you can display it by adding one more # at beginning and end in your string. Make sure the number of # at beginning and end must be same.
let string = ##”this is the string example with # character.”##
let regex = "^[A-Za-z0-9 !\"#$%&'()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~].{8,}$"
let regex = #”^[A-Za-z0-9 !"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~].{8,}$”#
isMultipleOf Added
In Swift4.0, if you want to find whether one number is multiple of another number or not? Then % operator is used. But before this operation, you need to check whether the second number is zero or not as belowlet Num1 = 15 let Num2 = 3 if Num2 != 0 && Num1 % Num2 == 0 { print("\(Num2) * \(Num1 / Num2) = \(Num1)") }
if Num1.isMultiple(of: Num2) { print("\(Num2) * \(Num1 / Num2) = \(Num1)") }
Count(where:) Added
In an earlier version of swift, for finding a specific object from the array, we use filter(_:) with predicates. A simple code with filter(_:) is given belowlet marks = [75, 39, 82, 23, 56, 46] let pass = marks.filter({ $0 > 35 }) print("Passing Subjects : \(pass)") //output : Passing Subjects : [75, 39, 82, 56, 46]
let marks = [75, 39, 82, 23, 56, 46, 64, 98] let passCount = marks.filter({ $0 > 35 }).count print("Passing Subjects Count : \(passCount)") //output : Passing Subjects Count : 5
let marks = [75, 39, 82, 23, 56, 46, 64, 98] let passCount = marks.count(where : { $0 > 35 }) print("Passing Subjects Count : \(passCount)") //output : Passing Subjects Count : 5
Handling Future Enum Cases
For switch statement, all cases must be covered. This is the swift’s one of the security feature. But this feature sometimes not suitable in our coding. For example, if we want to add a new case in the future then it is automatically called a default statement because we didn’t add this new feature. Now this problem can be solved with @unknown attribute. Example of this situation is belowenum Mobile { case iPhone 7 case iPhone 8 case iPhone X }
func getSelectedMobilePrice(name: Mobile) { switch name { case .iPhone 7: print(“Price : $649“) case . iPhone 8: print("Price : $767”) default: print(“We are not selling iPhoneX“) } }
func getSelectedLanguageDesc(name: LanguageName) { switch name { case .iPhone 7: print(“Price : $649“) case . iPhone 8: print("Price : $767”) unknow default: print(“We are not selling this mobile“) } }
Flatten Nested Optionals
Swift allows to create nested optionals. for examplefunc getResult() -> Any { return "Result" } func getOptionalResult() -> Any? { return "OptionalResult" } let a = getResult() as? String let b = getOptionalResult()() as? String print(“\(a), \(b)”) //output : Optional<String>, Optional<String>
let objCourse: Course?
let completionYear = try? objCourse?.getCompletionYear()
Identify Key Path
.self is used for accessing the values in earlier version of Swift 5.0 .import UIKit class Student { let standard: Int let marks: Int init(standard: Int, marks: Int) { self.standard = standard self.marks = marks } } var objStudent = Student(standard: 5, marks: 78) objStudent.self = Student(standard: 6, marks: 90) print(objStudent.standard) print(objStudent.marks)
objStudent[keyPath: \.self] = Student(standard: 6, marks: 90)
Properties added to Character
Swift 5.0 added many new properties to character that makes easier to use characters. 1.) isNewLine :- This property checks whether character represents a new line or not and return bool value. 2.) isNumber :- This property checks whether character represents a number or not and return bool value. 3.) isLetter :- This property checks whether character represents a letter or not and return bool value. 4.) uppercased() :- This property returns character in upper case same as String. 5.) lowercased() :- This property returns character in lower case same as String. 6.) isUpperCase :- This property checks whether character is uppercase or not and return bool value. 7.) isLowerCase :- This property checks whether character is lowercase or not and return bool value. Examplelet str = "AB01c8" print(str.first.isNewLine) //false print(str.last.isNumber) //true print(str.first.isLetter) //true print(str.first.uppercased()) //A print(str.first.lowercased()) //a print(str.first.isUpperCase) //true print(str.first.isLowerCase) //false
Properties added to Unicode.Scalar
We can find number count from string with Unicode scalar in Swift 4.2 like belowlet str = "AC120G" var count = 0 str.unicodeScalars.forEach { count += (65...90) ~= $0.value || (97...122) ~= $0.value ? 1 : 0 } print("number count = \(count)”)
str.unicodeScalars.forEach { count += $0.properties.isAlphabetic ? 1 : 0 }
CompactMapValues() function added to Dictionary
MapValues, reduce and filter are used to filter values from dictionary as belowlet dict: [String: String?] = ["1": "value1", "2": "value2", "3": nil] let dictFinal1 = dict.filter { $0.value != nil }.mapValues { $0! } let dictFinal2 = dict.reduce(into: [String: String]()) { (result, item) in result[item.key] = item.value } // dictFinal1 == ["1": "value1", "2": "value2"] // dictFinal1 == ["1": "value1", "2": "value2"]
let dictFinal = dict.compactMapValues({$0}) // dictFinal == ["1": "value1", "2": "value2"]
Dictionary Literals to KeyValuePairs
DictionaryLiteral is a little bit confusing and misnamed because it is neither a dictionary or a literal. It is just a key pair values. In Swift 4.2let marks: DictionaryLiteral = ["student1": "62", "student2": "85", "student3": "92"]
let marks: KeyValuePairs = ["student1": "62", "student2": "85", "student3": "92"]
String Interpolation Updates
In Swift 4.2, String interpolation can be implemented by interpolating segments like belowlet statement1 = "There are many updates in Swift 5.0 " let segment1 = String(stringInterpolationSegment: statement1) let statement2 = "and it makes easier." let segment2 = String(stringInterpolationSegment: statement2) let strFinalStatement = String(stringInterpolation: segment1, segment2) // “There are many updates in Swift 5.0 and it make easier.”
var interpolation = DefaultStringInterpolation(literalCapacity : 55, interpolationCount: 1) interpolation.appendLiteral("There are many updates in Swift 5.0 ") interpolation.appendLiteral("and it makes easier.") let strFinalStatement = String(stringInterpolation: interpolation)
Result type added to Standard Library
Swift 5.0 adds completely new type result to the standard library. It gives a simple and easy way to handle the error. It can be implemented as an enum which has two cases: Success and Failure. Success can be any type but Failure must be of type Error. Now you can use this type in your completion handler for getting the result. Let’s take one enum of type Error for failure handling.enum ConnectionError: Error { case wrongUrl }
func connectToServer(strUrl: String, completionHandler: @escaping (Result<Int, NetworkError>) -> Void) { guard let url = URL(string: strUrl) else { completionHandler(.failure(.wrongUrl)) return } print("connecting") completionHandler(.success("successfully connected")) }
connectToServer(strUrl: "www.google.com") { result in switch result { case .success(let strResult): print(strResult) case .failure(let error): print(error.localizedDescription) } } // “successfully connected”
connectToServer(strUrl: “testing .com“) { result in switch result { case .success(let strResult): print(strResult) case .failure(let error): print(error.localizedDescription) } } // wrongUrl
Dynamically callable types
@dynamicCallble is added to swift, which marks a type as being callable directly. In swift 4.2 @dynamicMemberLookup is available which make swift code easier and dynamic such as Python and JavaScript. @dynamicCallable is the extension of this attribute with the same purpose. Here is the example :-@dynamicCallable class TestDynamic { func dynamicallyCall(withArguments params: [Double]) -> Double? { guard !params.isEmpty else { return nil } return params.max() } func dynamicallyCall(withKeywordArguments params: KeyValuePairs<String, Int>) -> Double? { guard !params.isEmpty else { return nil } return params.reduce(0) { $1.key.isEmpty ? $0 : $0 + $1.value } } } let objTest = TestDynamic() objTest() // nil objTest(8, 10, 25) // 25 objTest(first: 8, 2, second: 2) // 10
Subsequence removed
In Swift 4.2, Sequence declares several methods that return a SubSequencefunc dropFirst(_:) -> SubSequence func dropLast(_:) -> SubSequence func drop(while:) -> SubSequence func prefix(_:) -> SubSequence func prefix(while:) -> SubSequence func suffix(_:) -> SubSequence func split(separator:) -> [SubSequence]
let sequence = [5, 2, 7, 4] sequence.dropFirst(2) // [7,4]
Package Manager Setting Updates
In Swift 5.0, you can specify the minimum required platform deployment target version in Package.swift file as followlet package = Package(name: “Test”, platforms: [ .macOS(.v10_14_1), .iOS(.v12_3), .tvOS(.v12_3), .watchOS(.v5) ])
Remove Customization Points From Collection.
In Swift 5.0, the following customization points have been removed from the standard library. 1. map, forEach and filter from Sequence 2. first, prefix(uptown:), prefix(through:) and suffix(from:) from Collection 3. last from BidirectionalCollectionInitializing Literals Via Coercion
If types conform to the literal protocol, literal initializers coerce the literal to its type.struct Test: ExpressibleByIntegerLiteral { typealias IntegerLiteralType = Int var objTest: Int init(integerLiteral value: IntegerLiteralType) { self.objTest = value } init?(_ possibleQuestion: IntegerLiteralType) { return nil } } // Swift 4.2 let objTest1 = Test(3) // 'nil' let objTest2 = 3 as Test // Test(objTest: 3) // Swift 5.0 let objTest1 = Test(3) // Test(objTest: 3) let objTest2 = 3 as Test // Test(objTest: 3)
Deprecate String Index Encoded Offsets
In Swift 4.2, Strings are encoded with UTF-16. So encodedOffset returns an offset into the UTF-16 format as belowlet str = "String With Swift 4.2" let offset = str.endIndex.encodedOffset
let str = "String With Swift 4.2" let offset = str.endIndex.utf16Offset(in: str)
Support ‘less than’ operator in compilation conditions
In Swift 4.2, “ >=“ operator is used for compilation conditions like below
#if !swift(>=5.0) print("Swift 4.2 available") #else print("Swift 5.0 available") #endif #if !compiler(>=5.0) print("Swift Compiler 4.2 available") #else print("Swift 5.0 available") #endif
#if swift(<5.0) print("Swift 4.2 available") #else print("Swift 5.0 available") #endif #if compiler(<5.0) print("Swift Compiler 4.2 available") #else print("Swift 5.0 available") #endif
Support Array instead of Variadic parameters for Enum
In Swift 4.2, we can use variadic parameters for enum cases as belowenum Subject { case Chapter(_: String...) } func getChapter() -> Subject { return .Chapter("Chapter1", "Chapter2", "Chapter3") }
enum Subject { case Chapter([String]) } func getChapter() -> Subject { return .Chapter([“Chapter1", "Chapter2", "Chapter3”]) }